d3d9/tests: Properly check for mipmap autogeneration support.
[wine.git] / dlls / d3d9 / tests / d3d9ex.c
bloba3cbdbfadfffab792cbcff57f88e3fcb4d807796
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
37 struct device_desc
39 HWND device_window;
40 unsigned int width;
41 unsigned int height;
42 DWORD flags;
45 static BOOL adapter_is_warp(const D3DADAPTER_IDENTIFIER9 *identifier)
47 return !strcmp(identifier->Driver, "d3d10warp.dll");
50 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
52 unsigned int i;
54 for (i = 0; i < 4; ++i)
56 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff)
57 return FALSE;
58 c1 >>= 8;
59 c2 >>= 8;
61 return TRUE;
64 static DWORD get_pixel_color(IDirect3DDevice9Ex *device, unsigned int x, unsigned int y)
66 IDirect3DSurface9 *surf = NULL, *target = NULL;
67 RECT rect = {x, y, x + 1, y + 1};
68 D3DLOCKED_RECT locked_rect;
69 D3DSURFACE_DESC desc;
70 HRESULT hr;
71 DWORD ret;
73 hr = IDirect3DDevice9Ex_GetRenderTarget(device, 0, &target);
74 if (FAILED(hr))
76 trace("Can't get the render target, hr %#x.\n", hr);
77 return 0xdeadbeed;
80 hr = IDirect3DSurface9_GetDesc(target, &desc);
81 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
82 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, desc.Width, desc.Height,
83 desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL);
84 if (FAILED(hr) || !surf)
86 trace("Can't create an offscreen plain surface to read the render target data, hr %#x.\n", hr);
87 ret = 0xdeadbeef;
88 goto out;
91 hr = IDirect3DDevice9Ex_GetRenderTargetData(device, target, surf);
92 if (FAILED(hr))
94 trace("Can't read the render target data, hr %#x.\n", hr);
95 ret = 0xdeadbeec;
96 goto out;
99 hr = IDirect3DSurface9_LockRect(surf, &locked_rect, &rect, D3DLOCK_READONLY);
100 if (FAILED(hr))
102 trace("Can't lock the offscreen surface, hr %#x.\n", hr);
103 ret = 0xdeadbeeb;
104 goto out;
107 /* Remove the X channel for now. DirectX and OpenGL have different
108 * ideas how to treat it apparently, and it isn't really important
109 * for these tests. */
110 ret = ((DWORD *)locked_rect.pBits)[0] & 0x00ffffff;
111 hr = IDirect3DSurface9_UnlockRect(surf);
112 if (FAILED(hr))
113 trace("Can't unlock the offscreen surface, hr %#x.\n", hr);
115 out:
116 if (target)
117 IDirect3DSurface9_Release(target);
118 if (surf)
119 IDirect3DSurface9_Release(surf);
120 return ret;
123 static HWND create_window(void)
125 WNDCLASSA wc = {0};
127 wc.lpfnWndProc = DefWindowProcA;
128 wc.lpszClassName = "d3d9_test_wc";
129 RegisterClassA(&wc);
131 return CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION,
132 0, 0, 640, 480, 0, 0, 0, 0);
135 /* try to make sure pending X events have been processed before continuing */
136 static void flush_events(void)
138 MSG msg;
139 int diff = 200;
140 int min_timeout = 100;
141 DWORD time = GetTickCount() + diff;
143 while (diff > 0)
145 if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT)
146 break;
147 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
148 DispatchMessageA(&msg);
149 diff = time - GetTickCount();
153 static IDirect3DDevice9Ex *create_device(HWND focus_window, const struct device_desc *desc)
155 D3DPRESENT_PARAMETERS present_parameters = {0};
156 IDirect3DDevice9Ex *device;
157 D3DDISPLAYMODEEX mode, *m;
158 IDirect3D9Ex *d3d9;
159 DWORD behavior_flags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
161 if (FAILED(pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9)))
162 return NULL;
164 present_parameters.BackBufferWidth = 640;
165 present_parameters.BackBufferHeight = 480;
166 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
167 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
168 present_parameters.hDeviceWindow = focus_window;
169 present_parameters.Windowed = TRUE;
170 present_parameters.EnableAutoDepthStencil = TRUE;
171 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
173 if (desc)
175 present_parameters.BackBufferWidth = desc->width;
176 present_parameters.BackBufferHeight = desc->height;
177 present_parameters.hDeviceWindow = desc->device_window;
178 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
179 if (desc->flags & CREATE_DEVICE_NOWINDOWCHANGES)
180 behavior_flags |= D3DCREATE_NOWINDOWCHANGES;
183 mode.Size = sizeof(mode);
184 mode.Width = present_parameters.BackBufferWidth;
185 mode.Height = present_parameters.BackBufferHeight;
186 mode.RefreshRate = 0;
187 mode.Format = D3DFMT_A8R8G8B8;
188 mode.ScanLineOrdering = 0;
190 m = present_parameters.Windowed ? NULL : &mode;
191 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
192 behavior_flags, &present_parameters, m, &device)))
193 goto done;
195 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
196 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
197 behavior_flags, &present_parameters, m, &device)))
198 goto done;
200 behavior_flags ^= (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
202 if (SUCCEEDED(IDirect3D9Ex_CreateDeviceEx(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
203 behavior_flags, &present_parameters, m, &device)))
204 goto done;
206 device = NULL;
208 done:
209 IDirect3D9Ex_Release(d3d9);
210 return device;
213 static HRESULT reset_device(IDirect3DDevice9Ex *device, const struct device_desc *desc)
215 D3DPRESENT_PARAMETERS present_parameters = {0};
217 present_parameters.BackBufferWidth = 640;
218 present_parameters.BackBufferHeight = 480;
219 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
220 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
221 present_parameters.hDeviceWindow = NULL;
222 present_parameters.Windowed = TRUE;
223 present_parameters.EnableAutoDepthStencil = TRUE;
224 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
226 if (desc)
228 present_parameters.BackBufferWidth = desc->width;
229 present_parameters.BackBufferHeight = desc->height;
230 present_parameters.hDeviceWindow = desc->device_window;
231 present_parameters.Windowed = !(desc->flags & CREATE_DEVICE_FULLSCREEN);
234 return IDirect3DDevice9_Reset(device, &present_parameters);
237 static ULONG getref(IUnknown *obj) {
238 IUnknown_AddRef(obj);
239 return IUnknown_Release(obj);
242 static void test_qi_base_to_ex(void)
244 IDirect3D9 *d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
245 IDirect3D9Ex *d3d9ex = (void *) 0xdeadbeef;
246 IDirect3DDevice9 *device;
247 IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
248 IDirect3DSwapChain9 *swapchain = NULL;
249 IDirect3DSwapChain9Ex *swapchainEx = (void *)0xdeadbeef;
250 HRESULT hr;
251 HWND window = create_window();
252 D3DPRESENT_PARAMETERS present_parameters;
254 if (!d3d9)
256 skip("Direct3D9 is not available\n");
257 return;
260 hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3D9Ex, (void **) &d3d9ex);
261 ok(hr == E_NOINTERFACE,
262 "IDirect3D9::QueryInterface for IID_IDirect3D9Ex returned %08x, expected E_NOINTERFACE\n",
263 hr);
264 ok(d3d9ex == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9ex);
265 if(d3d9ex) IDirect3D9Ex_Release(d3d9ex);
267 memset(&present_parameters, 0, sizeof(present_parameters));
268 present_parameters.Windowed = TRUE;
269 present_parameters.hDeviceWindow = window;
270 present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
271 present_parameters.BackBufferWidth = 640;
272 present_parameters.BackBufferHeight = 480;
273 present_parameters.EnableAutoDepthStencil = FALSE;
274 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
275 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
276 if(FAILED(hr)) {
277 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
278 goto out;
281 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
282 ok(hr == E_NOINTERFACE,
283 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected E_NOINTERFACE\n",
284 hr);
285 ok(deviceEx == NULL, "QueryInterface returned interface %p, expected NULL\n", deviceEx);
286 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
288 /* Get the implicit swapchain */
289 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
290 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x).\n", hr);
291 if (SUCCEEDED(hr))
293 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
294 ok(hr == E_NOINTERFACE,
295 "IDirect3DSwapChain9::QueryInterface for IID_IDirect3DSwapChain9Ex returned %08x, expected E_NOINTERFACE.\n",
296 hr);
297 ok(swapchainEx == NULL, "QueryInterface returned interface %p, expected NULL.\n", swapchainEx);
298 if (swapchainEx)
299 IDirect3DSwapChain9Ex_Release(swapchainEx);
301 if (swapchain)
302 IDirect3DSwapChain9_Release(swapchain);
304 IDirect3DDevice9_Release(device);
306 out:
307 IDirect3D9_Release(d3d9);
308 DestroyWindow(window);
311 static void test_qi_ex_to_base(void)
313 IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
314 IDirect3D9Ex *d3d9ex;
315 IDirect3DDevice9 *device;
316 IDirect3DDevice9Ex *deviceEx = (void *) 0xdeadbeef;
317 IDirect3DSwapChain9 *swapchain = NULL;
318 IDirect3DSwapChain9Ex *swapchainEx = (void *)0xdeadbeef;
319 HRESULT hr;
320 HWND window = create_window();
321 D3DPRESENT_PARAMETERS present_parameters;
322 ULONG ref;
324 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
325 ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "Direct3DCreate9Ex returned %08x\n", hr);
326 if(FAILED(hr)) {
327 skip("Direct3D9Ex is not available\n");
328 goto out;
331 hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
332 ok(hr == D3D_OK,
333 "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
334 hr);
335 ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
336 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
337 ref = getref((IUnknown *) d3d9ex);
338 ok(ref == 2, "IDirect3D9Ex refcount is %d, expected 2\n", ref);
339 ref = getref((IUnknown *) d3d9);
340 ok(ref == 2, "IDirect3D9 refcount is %d, expected 2\n", ref);
342 memset(&present_parameters, 0, sizeof(present_parameters));
343 present_parameters.Windowed = TRUE;
344 present_parameters.hDeviceWindow = window;
345 present_parameters.SwapEffect = D3DSWAPEFFECT_COPY;
346 present_parameters.BackBufferWidth = 640;
347 present_parameters.BackBufferHeight = 480;
348 present_parameters.EnableAutoDepthStencil = FALSE;
349 present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
351 /* First, try to create a normal device with IDirect3D9Ex::CreateDevice and QI it for IDirect3DDevice9Ex */
352 hr = IDirect3D9Ex_CreateDevice(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
353 if(FAILED(hr)) {
354 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
355 goto out;
358 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
359 ok(hr == D3D_OK,
360 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
361 hr);
362 ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
363 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
364 ref = getref((IUnknown *) device);
365 ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref);
366 ref = getref((IUnknown *) deviceEx);
367 ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref);
368 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
369 IDirect3DDevice9_Release(device);
371 /* Next, try to create a normal device with IDirect3D9::CreateDevice(non-ex) and QI it */
372 hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device);
373 if(FAILED(hr)) {
374 skip("Failed to create a regular Direct3DDevice9, skipping QI tests\n");
375 goto out;
378 hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9Ex, (void **) &deviceEx);
379 ok(hr == D3D_OK,
380 "IDirect3D9Device::QueryInterface for IID_IDirect3DDevice9Ex returned %08x, expected D3D_OK\n",
381 hr);
382 ok(deviceEx != NULL && deviceEx != (void *) 0xdeadbeef,
383 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", deviceEx);
384 ref = getref((IUnknown *) device);
385 ok(ref == 2, "IDirect3DDevice9 refcount is %d, expected 2\n", ref);
386 ref = getref((IUnknown *) deviceEx);
387 ok(ref == 2, "IDirect3DDevice9Ex refcount is %d, expected 2\n", ref);
389 /* Get the implicit swapchain */
390 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
391 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x).\n", hr);
392 if (SUCCEEDED(hr))
394 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
395 ok(hr == D3D_OK,
396 "IDirect3DSwapChain9::QueryInterface for IID_IDirect3DSwapChain9Ex returned %08x, expected D3D_OK.\n",
397 hr);
398 ok(swapchainEx != NULL && swapchainEx != (void *)0xdeadbeef,
399 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef.\n", swapchainEx);
400 if (swapchainEx)
401 IDirect3DSwapChain9Ex_Release(swapchainEx);
403 if (swapchain)
404 IDirect3DSwapChain9_Release(swapchain);
406 if(deviceEx) IDirect3DDevice9Ex_Release(deviceEx);
407 IDirect3DDevice9_Release(device);
409 IDirect3D9_Release(d3d9);
410 IDirect3D9Ex_Release(d3d9ex);
412 out:
413 DestroyWindow(window);
416 static void test_get_adapter_luid(void)
418 HWND window = create_window();
419 IDirect3D9Ex *d3d9ex;
420 UINT count;
421 HRESULT hr;
422 LUID luid;
424 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
425 if (FAILED(hr))
427 skip("Direct3D9Ex is not available.\n");
428 DestroyWindow(window);
429 return;
432 count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
433 if (!count)
435 skip("No adapters available.\n");
436 IDirect3D9Ex_Release(d3d9ex);
437 DestroyWindow(window);
438 return;
441 hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, D3DADAPTER_DEFAULT, &luid);
442 ok(SUCCEEDED(hr), "GetAdapterLUID failed, hr %#x.\n", hr);
443 trace("adapter luid: %08x:%08x.\n", luid.HighPart, luid.LowPart);
445 IDirect3D9Ex_Release(d3d9ex);
448 static void test_swapchain_get_displaymode_ex(void)
450 IDirect3DSwapChain9 *swapchain = NULL;
451 IDirect3DSwapChain9Ex *swapchainEx = NULL;
452 IDirect3DDevice9Ex *device;
453 D3DDISPLAYMODE mode;
454 D3DDISPLAYMODEEX mode_ex;
455 D3DDISPLAYROTATION rotation;
456 HWND window;
457 HRESULT hr;
459 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
460 0, 0, 640, 480, 0, 0, 0, 0);
461 if (!(device = create_device(window, NULL)))
463 skip("Failed to create a D3D device, skipping swapchain GetDisplayModeEx tests.\n");
464 goto out;
467 /* Get the implicit swapchain */
468 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
469 if (FAILED(hr))
471 skip("Failed to get the implicit swapchain, skipping swapchain GetDisplayModeEx tests.\n");
472 goto out;
475 hr = IDirect3DSwapChain9_QueryInterface(swapchain, &IID_IDirect3DSwapChain9Ex, (void **)&swapchainEx);
476 IDirect3DSwapChain9_Release(swapchain);
477 if (FAILED(hr))
479 skip("Failed to QI for IID_IDirect3DSwapChain9Ex, skipping swapchain GetDisplayModeEx tests.\n");
480 goto out;
483 /* invalid size */
484 memset(&mode_ex, 0, sizeof(mode_ex));
485 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, &rotation);
486 ok(hr == D3DERR_INVALIDCALL, "GetDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL.\n", hr);
488 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
489 rotation = (D3DDISPLAYROTATION)0xdeadbeef;
490 /* valid count and valid size */
491 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, &rotation);
492 ok(SUCCEEDED(hr), "GetDisplayModeEx failed, hr %#x.\n", hr);
494 /* compare what GetDisplayMode returns with what GetDisplayModeEx returns */
495 hr = IDirect3DSwapChain9Ex_GetDisplayMode(swapchainEx, &mode);
496 ok(SUCCEEDED(hr), "GetDisplayMode failed, hr %#x.\n", hr);
498 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "Size is %d.\n", mode_ex.Size);
499 ok(mode_ex.Width == mode.Width, "Width is %d instead of %d.\n", mode_ex.Width, mode.Width);
500 ok(mode_ex.Height == mode.Height, "Height is %d instead of %d.\n", mode_ex.Height, mode.Height);
501 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d.\n",
502 mode_ex.RefreshRate, mode.RefreshRate);
503 ok(mode_ex.Format == mode.Format, "Format is %x instead of %x.\n", mode_ex.Format, mode.Format);
504 /* Don't know yet how to test for ScanLineOrdering, just testing that it
505 * is set to a value by GetDisplayModeEx(). */
506 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0.\n");
507 /* Don't know how to compare the rotation in this case, test that it is set */
508 ok(rotation != (D3DDISPLAYROTATION)0xdeadbeef, "rotation is %d, expected != 0xdeadbeef.\n", rotation);
510 trace("GetDisplayModeEx returned Width = %d, Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d.\n",
511 mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);
513 /* test GetDisplayModeEx with null pointer for D3DDISPLAYROTATION */
514 memset(&mode_ex, 0, sizeof(mode_ex));
515 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
517 hr = IDirect3DSwapChain9Ex_GetDisplayModeEx(swapchainEx, &mode_ex, NULL);
518 ok(SUCCEEDED(hr), "GetDisplayModeEx failed, hr %#x.\n", hr);
520 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "Size is %d.\n", mode_ex.Size);
521 ok(mode_ex.Width == mode.Width, "Width is %d instead of %d.\n", mode_ex.Width, mode.Width);
522 ok(mode_ex.Height == mode.Height, "Height is %d instead of %d.\n", mode_ex.Height, mode.Height);
523 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d.\n",
524 mode_ex.RefreshRate, mode.RefreshRate);
525 ok(mode_ex.Format == mode.Format, "Format is %x instead of %x.\n", mode_ex.Format, mode.Format);
526 /* Don't know yet how to test for ScanLineOrdering, just testing that it
527 * is set to a value by GetDisplayModeEx(). */
528 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0.\n");
530 IDirect3DSwapChain9Ex_Release(swapchainEx);
532 out:
533 if (device)
534 IDirect3DDevice9Ex_Release(device);
535 DestroyWindow(window);
538 static void test_get_adapter_displaymode_ex(void)
540 HWND window = create_window();
541 IDirect3D9 *d3d9 = (void *) 0xdeadbeef;
542 IDirect3D9Ex *d3d9ex;
543 UINT count;
544 HRESULT hr;
545 D3DDISPLAYMODE mode;
546 D3DDISPLAYMODEEX mode_ex;
547 D3DDISPLAYROTATION rotation;
548 DEVMODEW startmode, devmode;
549 LONG retval;
551 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
552 if (FAILED(hr))
554 skip("Direct3D9Ex is not available (%#x)\n", hr);
555 DestroyWindow(window);
556 return;
559 count = IDirect3D9Ex_GetAdapterCount(d3d9ex);
560 if (!count)
562 skip("No adapters available.\n");
563 IDirect3D9Ex_Release(d3d9ex);
564 DestroyWindow(window);
565 return;
568 hr = IDirect3D9Ex_QueryInterface(d3d9ex, &IID_IDirect3D9, (void **) &d3d9);
569 ok(hr == D3D_OK,
570 "IDirect3D9Ex::QueryInterface for IID_IDirect3D9 returned %08x, expected D3D_OK\n",
571 hr);
572 ok(d3d9 != NULL && d3d9 != (void *) 0xdeadbeef,
573 "QueryInterface returned interface %p, expected != NULL && != 0xdeadbeef\n", d3d9);
575 memset(&startmode, 0, sizeof(startmode));
576 startmode.dmSize = sizeof(startmode);
577 retval = EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &startmode, 0);
578 ok(retval, "Failed to retrieve current display mode, retval %d.\n", retval);
579 if (!retval) goto out;
581 devmode = startmode;
582 devmode.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT;
583 S2(U1(devmode)).dmDisplayOrientation = DMDO_180;
584 retval = ChangeDisplaySettingsExW(NULL, &devmode, NULL, 0, NULL);
585 if (retval == DISP_CHANGE_BADMODE)
587 skip("Graphics mode is not supported.\n");
588 goto out;
591 ok(retval == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsEx failed with %d.\n", retval);
592 /* try retrieve orientation info with EnumDisplaySettingsEx*/
593 devmode.dmFields = 0;
594 S2(U1(devmode)).dmDisplayOrientation = 0;
595 ok(EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &devmode, EDS_ROTATEDMODE),
596 "EnumDisplaySettingsEx failed.\n");
598 /*now that orientation has changed start tests for GetAdapterDisplayModeEx: invalid Size*/
599 memset(&mode_ex, 0, sizeof(mode_ex));
600 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
601 ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);
603 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
604 /* invalid count*/
605 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, count + 1, &mode_ex, &rotation);
606 ok(hr == D3DERR_INVALIDCALL, "GetAdapterDisplayModeEx returned %#x instead of D3DERR_INVALIDCALL\n", hr);
607 /*valid count and valid Size*/
608 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, &rotation);
609 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);
611 /* Compare what GetAdapterDisplayMode returns with what GetAdapterDisplayModeEx returns*/
612 hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &mode);
613 ok(SUCCEEDED(hr), "GetAdapterDisplayMode failed, hr %#x.\n", hr);
615 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
616 ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
617 ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
618 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n",
619 mode_ex.RefreshRate, mode.RefreshRate);
620 ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
621 /* Don't know yet how to test for ScanLineOrdering, just testing that it
622 * is set to a value by GetAdapterDisplayModeEx(). */
623 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
624 /* Check that orientation is returned correctly by GetAdapterDisplayModeEx
625 * and EnumDisplaySettingsEx(). */
626 todo_wine ok(S2(U1(devmode)).dmDisplayOrientation == DMDO_180 && rotation == D3DDISPLAYROTATION_180,
627 "rotation is %d instead of %d\n", rotation, S2(U1(devmode)).dmDisplayOrientation);
629 trace("GetAdapterDisplayModeEx returned Width = %d, Height = %d, RefreshRate = %d, Format = %x, ScanLineOrdering = %x, rotation = %d\n",
630 mode_ex.Width, mode_ex.Height, mode_ex.RefreshRate, mode_ex.Format, mode_ex.ScanLineOrdering, rotation);
632 /* test GetAdapterDisplayModeEx with null pointer for D3DDISPLAYROTATION */
633 memset(&mode_ex, 0, sizeof(mode_ex));
634 mode_ex.Size = sizeof(D3DDISPLAYMODEEX);
636 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9ex, D3DADAPTER_DEFAULT, &mode_ex, NULL);
637 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);
639 ok(mode_ex.Size == sizeof(D3DDISPLAYMODEEX), "size is %d\n", mode_ex.Size);
640 ok(mode_ex.Width == mode.Width, "width is %d instead of %d\n", mode_ex.Width, mode.Width);
641 ok(mode_ex.Height == mode.Height, "height is %d instead of %d\n", mode_ex.Height, mode.Height);
642 ok(mode_ex.RefreshRate == mode.RefreshRate, "RefreshRate is %d instead of %d\n",
643 mode_ex.RefreshRate, mode.RefreshRate);
644 ok(mode_ex.Format == mode.Format, "format is %x instead of %x\n", mode_ex.Format, mode.Format);
645 /* Don't know yet how to test for ScanLineOrdering, just testing that it
646 * is set to a value by GetAdapterDisplayModeEx(). */
647 ok(mode_ex.ScanLineOrdering != 0, "ScanLineOrdering returned 0\n");
649 /* return to the default mode */
650 retval = ChangeDisplaySettingsExW(NULL, &startmode, NULL, 0, NULL);
651 ok(retval == DISP_CHANGE_SUCCESSFUL, "ChangeDisplaySettingsEx failed with %d.\n", retval);
652 out:
653 IDirect3D9_Release(d3d9);
654 IDirect3D9Ex_Release(d3d9ex);
655 DestroyWindow(window);
658 static void test_create_depth_stencil_surface_ex(void)
660 static const struct
662 DWORD usage;
663 HRESULT hr;
664 BOOL broken_warp;
666 tests[] =
668 {0, D3D_OK, FALSE},
669 {D3DUSAGE_DEPTHSTENCIL, D3DERR_INVALIDCALL, FALSE},
670 {D3DUSAGE_RESTRICTED_CONTENT, D3D_OK, TRUE},
673 D3DADAPTER_IDENTIFIER9 identifier;
674 D3DSURFACE_DESC surface_desc;
675 IDirect3DDevice9Ex *device;
676 IDirect3DSurface9 *surface;
677 IDirect3D9 *d3d;
678 unsigned int i;
679 HWND window;
680 HRESULT hr;
681 ULONG ref;
682 BOOL warp;
684 window = create_window();
686 if (!(device = create_device(window, NULL)))
688 skip("Failed to create a D3D device.\n");
689 DestroyWindow(window);
690 return;
693 hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d);
694 ok(SUCCEEDED(hr), "Failed to get Direct3D9, hr %#x.\n", hr);
695 hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
696 ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#x.\n", hr);
697 warp = adapter_is_warp(&identifier);
698 IDirect3D9_Release(d3d);
700 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
702 surface = (IDirect3DSurface9 *)0xdeadbeef;
703 hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(device, 64, 64, D3DFMT_D24S8,
704 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL, tests[i].usage);
705 ok(hr == tests[i].hr || broken(warp && tests[i].broken_warp),
706 "Test %u: Got unexpected hr %#x.\n", i, hr);
707 if (SUCCEEDED(hr))
709 hr = IDirect3DSurface9_GetDesc(surface, &surface_desc);
710 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
711 ok(surface_desc.Type == D3DRTYPE_SURFACE, "Test %u: Got unexpected type %#x.\n",
712 i, surface_desc.Type);
713 ok(surface_desc.Pool == D3DPOOL_DEFAULT, "Test %u: Got unexpected pool %#x.\n",
714 i, surface_desc.Pool);
715 ok(surface_desc.Usage == (tests[i].usage | D3DUSAGE_DEPTHSTENCIL),
716 "Test %u: Got unexpected usage %#x.\n", i, surface_desc.Usage);
718 ref = IDirect3DSurface9_Release(surface);
719 ok(!ref, "Test %u: Surface has %u references left.\n", i, ref);
721 else
723 ok(surface == (IDirect3DSurface9 *)0xdeadbeef || broken(warp && tests[i].broken_warp),
724 "Test %u: Got unexpected surface pointer %p.\n", i, surface);
728 ref = IDirect3DDevice9Ex_Release(device);
729 ok(!ref, "Device has %u references left.\n", ref);
730 DestroyWindow(window);
733 static void test_user_memory(void)
735 static const struct
737 float x, y, z;
738 float u, v;
740 quad[] =
742 {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
743 {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f},
744 { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
745 { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
747 IDirect3DDevice9Ex *device;
748 IDirect3DTexture9 *texture, *texture2;
749 IDirect3DCubeTexture9 *cube_texture;
750 IDirect3DVolumeTexture9 *volume_texture;
751 IDirect3DVertexBuffer9 *vertex_buffer;
752 IDirect3DIndexBuffer9 *index_buffer;
753 IDirect3DSurface9 *surface;
754 D3DLOCKED_RECT locked_rect;
755 UINT refcount;
756 HWND window;
757 HRESULT hr;
758 void *mem;
759 char *ptr;
760 D3DCAPS9 caps;
761 unsigned int x, y;
762 D3DCOLOR color;
764 window = create_window();
765 if (!(device = create_device(window, NULL)))
767 skip("Failed to create a D3D device, skipping tests.\n");
768 goto done;
771 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
772 ok(SUCCEEDED(hr), "Failed to get caps, hr %#x.\n", hr);
774 mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 128 * 128 * 4);
775 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 0, 0, D3DFMT_A8R8G8B8,
776 D3DPOOL_SYSTEMMEM, &texture, &mem);
777 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
778 hr = IDirect3DDevice9Ex_CreateTexture(device, 1, 1, 0, 0, D3DFMT_A8R8G8B8,
779 D3DPOOL_SYSTEMMEM, &texture, &mem);
780 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
781 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 2, 0, D3DFMT_A8R8G8B8,
782 D3DPOOL_SYSTEMMEM, &texture, &mem);
783 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
784 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
785 D3DPOOL_SCRATCH, &texture, &mem);
786 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
788 hr = IDirect3DDevice9Ex_CreateTexture(device, 128, 128, 1, 0, D3DFMT_A8R8G8B8,
789 D3DPOOL_SYSTEMMEM, &texture, &mem);
790 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
791 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
792 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
793 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
794 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
795 hr = IDirect3DTexture9_UnlockRect(texture, 0);
796 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
797 IDirect3DTexture9_Release(texture);
799 if (caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
801 hr = IDirect3DDevice9Ex_CreateCubeTexture(device, 2, 1, 0, D3DFMT_A8R8G8B8,
802 D3DPOOL_SYSTEMMEM, &cube_texture, &mem);
803 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
805 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
807 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 2, 2, 2, 1, 0, D3DFMT_A8R8G8B8,
808 D3DPOOL_SYSTEMMEM, &volume_texture, &mem);
809 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
812 hr = IDirect3DDevice9Ex_CreateIndexBuffer(device, 16, 0, D3DFMT_INDEX32, D3DPOOL_SYSTEMMEM,
813 &index_buffer, &mem);
814 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
815 hr = IDirect3DDevice9Ex_CreateVertexBuffer(device, 16, 0, 0, D3DPOOL_SYSTEMMEM,
816 &vertex_buffer, &mem);
817 ok(hr == D3DERR_NOTAVAILABLE, "Got unexpected hr %#x.\n", hr);
819 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 128, 128, D3DFMT_A8R8G8B8,
820 D3DPOOL_SYSTEMMEM, &surface, &mem);
821 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
822 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
823 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
824 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
825 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
826 hr = IDirect3DSurface9_UnlockRect(surface);
827 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
828 IDirect3DSurface9_Release(surface);
830 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 128, 128, D3DFMT_A8R8G8B8,
831 D3DPOOL_SYSTEMMEM, &surface, &mem, 0);
832 todo_wine ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
833 if (SUCCEEDED(hr))
835 hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
836 ok(SUCCEEDED(hr), "Failed to lock surface, hr %#x.\n", hr);
837 ok(locked_rect.Pitch == 128 * 4, "Got unexpected pitch %d.\n", locked_rect.Pitch);
838 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
839 hr = IDirect3DSurface9_UnlockRect(surface);
840 ok(SUCCEEDED(hr), "Failed to unlock surface, hr %#x.\n", hr);
841 IDirect3DSurface9_Release(surface);
844 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 128, 128, D3DFMT_A8R8G8B8,
845 D3DPOOL_SCRATCH, &surface, &mem);
846 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
847 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 128, 128, D3DFMT_A8R8G8B8,
848 D3DPOOL_SCRATCH, &surface, &mem, 0);
849 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
851 ptr = mem;
852 for (y = 0; y < 33; ++y)
853 for (x = 0; x < 33; ++x)
854 *ptr++ = x * 255 / 32;
856 hr = IDirect3DDevice9Ex_CreateTexture(device, 33, 33, 1, 0, D3DFMT_L8,
857 D3DPOOL_SYSTEMMEM, &texture, &mem);
858 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
859 hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
860 ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
861 ok(locked_rect.Pitch == 33, "Got unexpected pitch %d.\n", locked_rect.Pitch);
862 ok(locked_rect.pBits == mem, "Got unexpected pBits %p, expected %p.\n", locked_rect.pBits, mem);
863 hr = IDirect3DTexture9_UnlockRect(texture, 0);
864 ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
866 hr = IDirect3DDevice9Ex_CreateTexture(device, 33, 33, 1, 0, D3DFMT_L8,
867 D3DPOOL_DEFAULT, &texture2, NULL);
868 ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
869 hr = IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)texture,
870 (IDirect3DBaseTexture9 *)texture2);
871 ok(SUCCEEDED(hr), "Failed to update texture, hr %#x.\n", hr);
873 hr = IDirect3DDevice9Ex_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
874 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
876 hr = IDirect3DDevice9Ex_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
877 ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr);
878 hr = IDirect3DDevice9Ex_SetRenderState(device, D3DRS_LIGHTING, FALSE);
879 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
880 hr = IDirect3DDevice9Ex_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture2);
881 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
883 hr = IDirect3DDevice9Ex_BeginScene(device);
884 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
885 hr = IDirect3DDevice9Ex_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
886 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
887 hr = IDirect3DDevice9Ex_EndScene(device);
888 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
890 color = get_pixel_color(device, 320, 240);
891 ok(color_match(color, 0x007f7f7f, 2), "Got unexpected color %#x.\n", color);
892 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
893 ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
895 hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
896 ok(SUCCEEDED(hr), "Failed to set texture, hr %#x.\n", hr);
897 IDirect3DTexture9_Release(texture2);
898 IDirect3DTexture9_Release(texture);
899 HeapFree(GetProcessHeap(), 0, mem);
900 refcount = IDirect3DDevice9Ex_Release(device);
901 ok(!refcount, "Device has %u references left.\n", refcount);
903 done:
904 DestroyWindow(window);
907 static void test_reset(void)
909 static const DWORD simple_vs[] =
911 0xfffe0101, /* vs_1_1 */
912 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
913 0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0 */
914 0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1 */
915 0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2 */
916 0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3 */
917 0x0000ffff, /* end */
920 DWORD height, orig_height = GetSystemMetrics(SM_CYSCREEN);
921 DWORD width, orig_width = GetSystemMetrics(SM_CXSCREEN);
922 IDirect3DVertexShader9 *shader;
923 IDirect3DSwapChain9 *swapchain;
924 D3DDISPLAYMODE d3ddm, d3ddm2;
925 D3DPRESENT_PARAMETERS d3dpp;
926 IDirect3DDevice9Ex *device;
927 IDirect3DSurface9 *surface;
928 UINT i, adapter_mode_count;
929 DEVMODEW devmode;
930 IDirect3D9 *d3d9;
931 D3DVIEWPORT9 vp;
932 D3DCAPS9 caps;
933 UINT refcount;
934 DWORD value;
935 HWND window;
936 HRESULT hr;
937 RECT rect;
938 LONG ret;
939 struct
941 UINT w;
942 UINT h;
943 } *modes = NULL;
944 UINT mode_count = 0;
946 window = create_window();
947 if (!(device = create_device(window, NULL)))
949 skip("Failed to create a D3D device, skipping test.\n");
950 DestroyWindow(window);
951 return;
954 hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d9);
955 ok(SUCCEEDED(hr), "Failed to get d3d9, hr %#x.\n", hr);
956 hr = IDirect3DDevice9Ex_GetDeviceCaps(device, &caps);
957 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
959 IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &d3ddm);
960 adapter_mode_count = IDirect3D9_GetAdapterModeCount(d3d9, D3DADAPTER_DEFAULT, d3ddm.Format);
961 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
962 for (i = 0; i < adapter_mode_count; ++i)
964 UINT j;
966 hr = IDirect3D9_EnumAdapterModes(d3d9, D3DADAPTER_DEFAULT, d3ddm.Format, i, &d3ddm2);
967 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
969 for (j = 0; j < mode_count; ++j)
971 if (modes[j].w == d3ddm2.Width && modes[j].h == d3ddm2.Height)
972 break;
974 if (j == mode_count)
976 modes[j].w = d3ddm2.Width;
977 modes[j].h = d3ddm2.Height;
978 ++mode_count;
981 /* We use them as invalid modes. */
982 if ((d3ddm2.Width == 801 && d3ddm2.Height == 600)
983 || (d3ddm2.Width == 32 && d3ddm2.Height == 32))
985 skip("This system supports a screen resolution of %dx%d, not running mode tests.\n",
986 d3ddm2.Width, d3ddm2.Height);
987 goto cleanup;
991 if (mode_count < 2)
993 skip("Less than 2 modes supported, skipping mode tests.\n");
994 goto cleanup;
997 i = 0;
998 if (modes[i].w == orig_width && modes[i].h == orig_height)
999 ++i;
1001 memset(&d3dpp, 0, sizeof(d3dpp));
1002 d3dpp.Windowed = FALSE;
1003 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1004 d3dpp.BackBufferWidth = modes[i].w;
1005 d3dpp.BackBufferHeight = modes[i].h;
1006 d3dpp.BackBufferFormat = d3ddm.Format;
1007 d3dpp.EnableAutoDepthStencil = TRUE;
1008 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1009 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1010 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1011 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1012 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1014 width = GetSystemMetrics(SM_CXSCREEN);
1015 height = GetSystemMetrics(SM_CYSCREEN);
1016 ok(width == modes[i].w, "Got screen width %u, expected %u.\n", width, modes[i].w);
1017 ok(height == modes[i].h, "Got screen height %u, expected %u.\n", height, modes[i].h);
1019 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1020 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1021 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].w && rect.bottom == modes[i].h,
1022 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1024 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1025 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1026 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1027 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1028 ok(vp.Width == modes[i].w, "Got vp.Width %u, expected %u.\n", vp.Width, modes[i].w);
1029 ok(vp.Height == modes[i].h, "Got vp.Height %u, expected %u.\n", vp.Height, modes[i].h);
1030 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1031 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1033 i = 1;
1034 vp.X = 10;
1035 vp.Y = 20;
1036 vp.MinZ = 2.0f;
1037 vp.MaxZ = 3.0f;
1038 hr = IDirect3DDevice9Ex_SetViewport(device, &vp);
1039 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
1041 SetRect(&rect, 10, 20, 30, 40);
1042 hr = IDirect3DDevice9Ex_SetScissorRect(device, &rect);
1043 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
1045 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1046 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1047 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1048 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1049 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1051 memset(&d3dpp, 0, sizeof(d3dpp));
1052 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1053 d3dpp.Windowed = FALSE;
1054 d3dpp.BackBufferWidth = modes[i].w;
1055 d3dpp.BackBufferHeight = modes[i].h;
1056 d3dpp.BackBufferFormat = d3ddm.Format;
1057 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1058 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1059 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1060 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1062 /* Render states are preserved in d3d9ex. */
1063 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1064 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1065 ok(!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1067 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1068 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1069 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].w && rect.bottom == modes[i].h,
1070 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1072 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1073 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1074 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1075 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1076 ok(vp.Width == modes[i].w, "Got vp.Width %u, expected %u.\n", vp.Width, modes[i].w);
1077 ok(vp.Height == modes[i].h, "Got vp.Height %u, expected %u.\n", vp.Height, modes[i].h);
1078 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1079 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1081 width = GetSystemMetrics(SM_CXSCREEN);
1082 height = GetSystemMetrics(SM_CYSCREEN);
1083 ok(width == modes[i].w, "Got screen width %u, expected %u.\n", width, modes[i].w);
1084 ok(height == modes[i].h, "Got screen height %u, expected %u.\n", height, modes[i].h);
1086 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1087 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1088 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1089 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1090 ok(d3dpp.BackBufferWidth == modes[i].w, "Got backbuffer width %u, expected %u.\n",
1091 d3dpp.BackBufferWidth, modes[i].w);
1092 ok(d3dpp.BackBufferHeight == modes[i].h, "Got backbuffer height %u, expected %u.\n",
1093 d3dpp.BackBufferHeight, modes[i].h);
1094 IDirect3DSwapChain9_Release(swapchain);
1096 memset(&d3dpp, 0, sizeof(d3dpp));
1097 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1098 d3dpp.Windowed = TRUE;
1099 d3dpp.BackBufferWidth = 400;
1100 d3dpp.BackBufferHeight = 300;
1101 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1102 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1103 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1104 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1105 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1107 width = GetSystemMetrics(SM_CXSCREEN);
1108 height = GetSystemMetrics(SM_CYSCREEN);
1109 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1110 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1112 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1113 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1114 ok(rect.left == 0 && rect.top == 0 && rect.right == 400 && rect.bottom == 300,
1115 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1117 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1118 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1119 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1120 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1121 ok(vp.Width == 400, "Got unexpected vp.Width %u.\n", vp.Width);
1122 ok(vp.Height == 300, "Got unexpected vp.Height %u.\n", vp.Height);
1123 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1124 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1126 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1127 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1128 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1129 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1130 ok(d3dpp.BackBufferWidth == 400, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1131 ok(d3dpp.BackBufferHeight == 300, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1132 IDirect3DSwapChain9_Release(swapchain);
1134 memset(&devmode, 0, sizeof(devmode));
1135 devmode.dmSize = sizeof(devmode);
1136 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1137 devmode.dmPelsWidth = modes[1].w;
1138 devmode.dmPelsHeight = modes[1].h;
1139 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1140 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1141 width = GetSystemMetrics(SM_CXSCREEN);
1142 height = GetSystemMetrics(SM_CYSCREEN);
1143 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1144 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1146 d3dpp.BackBufferWidth = 500;
1147 d3dpp.BackBufferHeight = 400;
1148 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1149 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1150 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1151 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1152 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1154 width = GetSystemMetrics(SM_CXSCREEN);
1155 height = GetSystemMetrics(SM_CYSCREEN);
1156 ok(width == modes[1].w, "Screen width is %u, expected %u.\n", width, modes[1].w);
1157 ok(height == modes[1].h, "Screen height is %u, expected %u.\n", height, modes[1].h);
1159 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1160 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1161 ok(rect.left == 0 && rect.top == 0 && rect.right == 500 && rect.bottom == 400,
1162 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1164 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1165 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1166 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1167 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1168 ok(vp.Width == 500, "Got unexpected vp.Width %u.\n", vp.Width);
1169 ok(vp.Height == 400, "Got unexpected vp.Height %u.\n", vp.Height);
1170 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1171 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1173 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1174 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1175 memset(&d3dpp, 0, sizeof(d3dpp));
1176 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1177 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1178 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1179 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1180 IDirect3DSwapChain9_Release(swapchain);
1182 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1183 devmode.dmPelsWidth = orig_width;
1184 devmode.dmPelsHeight = orig_height;
1185 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1186 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1187 width = GetSystemMetrics(SM_CXSCREEN);
1188 height = GetSystemMetrics(SM_CYSCREEN);
1189 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1190 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1192 SetRect(&rect, 0, 0, 200, 150);
1193 ok(AdjustWindowRect(&rect, GetWindowLongW(window, GWL_STYLE), FALSE), "Failed to adjust window rect.\n");
1194 ok(SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
1195 SWP_NOMOVE | SWP_NOZORDER), "Failed to set window position.\n");
1197 memset(&d3dpp, 0, sizeof(d3dpp));
1198 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1199 d3dpp.Windowed = TRUE;
1200 d3dpp.BackBufferWidth = 0;
1201 d3dpp.BackBufferHeight = 0;
1202 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1203 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1204 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1205 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1206 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1208 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1209 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1210 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1211 d3dpp.BackBufferFormat, d3ddm.Format);
1212 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1213 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1214 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1215 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1216 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1217 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1218 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1219 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1220 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1221 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1222 d3dpp.FullScreen_RefreshRateInHz);
1223 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1225 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1226 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1227 ok(rect.left == 0 && rect.top == 0 && rect.right == 200 && rect.bottom == 150,
1228 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1230 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1231 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1232 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1233 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1234 ok(vp.Width == 200, "Got unexpected vp.Width %u.\n", vp.Width);
1235 ok(vp.Height == 150, "Got unexpected vp.Height %u.\n", vp.Height);
1236 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1237 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1239 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1240 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1241 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1242 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1243 ok(d3dpp.BackBufferWidth == 200, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1244 ok(d3dpp.BackBufferHeight == 150, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1245 ok(d3dpp.BackBufferFormat == d3ddm.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1246 d3dpp.BackBufferFormat, d3ddm.Format);
1247 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1248 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1249 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1250 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1251 ok(d3dpp.hDeviceWindow == window, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, window);
1252 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1253 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1254 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1255 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1256 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1257 d3dpp.FullScreen_RefreshRateInHz);
1258 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1259 IDirect3DSwapChain9_Release(swapchain);
1261 memset(&d3dpp, 0, sizeof(d3dpp));
1262 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1263 d3dpp.Windowed = TRUE;
1264 d3dpp.BackBufferWidth = 400;
1265 d3dpp.BackBufferHeight = 300;
1267 /* Reset with resources in the default pool succeeds in d3d9ex. */
1268 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1269 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &surface, NULL);
1270 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1271 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1272 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1273 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1274 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1275 IDirect3DSurface9_Release(surface);
1277 if (caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP)
1279 IDirect3DVolumeTexture9 *volume_texture;
1281 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 16, 16, 4, 1, 0,
1282 D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &volume_texture, NULL);
1283 ok(SUCCEEDED(hr), "Failed to create volume texture, hr %#x.\n", hr);
1284 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1285 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1286 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1287 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1288 IDirect3DVolumeTexture9_Release(volume_texture);
1290 else
1292 skip("Volume textures not supported.\n");
1295 /* Scratch and sysmem pools are fine too. */
1296 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1297 D3DFMT_R5G6B5, D3DPOOL_SCRATCH, &surface, NULL);
1298 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1299 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1300 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1301 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1302 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1303 IDirect3DSurface9_Release(surface);
1305 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1306 D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &surface, NULL);
1307 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1308 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1309 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1310 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1311 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1312 IDirect3DSurface9_Release(surface);
1314 /* The depth stencil should get reset to the auto depth stencil when present. */
1315 hr = IDirect3DDevice9Ex_SetDepthStencilSurface(device, NULL);
1316 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
1318 d3dpp.EnableAutoDepthStencil = TRUE;
1319 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1320 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1321 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1322 hr = IDirect3DDevice9Ex_GetDepthStencilSurface(device, &surface);
1323 ok(SUCCEEDED(hr), "Failed to get depth/stencil surface, hr %#x.\n", hr);
1324 ok(!!surface, "Depth/stencil surface should not be NULL.\n");
1325 IDirect3DSurface9_Release(surface);
1327 d3dpp.EnableAutoDepthStencil = FALSE;
1328 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1329 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1330 hr = IDirect3DDevice9Ex_GetDepthStencilSurface(device, &surface);
1331 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1332 ok(!surface, "Depth/stencil surface should be NULL.\n");
1334 /* References to implicit surfaces are allowed in d3d9ex. */
1335 hr = IDirect3DDevice9Ex_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
1336 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
1337 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1338 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1339 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1340 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1341 IDirect3DSurface9_Release(surface);
1343 /* Shaders are fine. */
1344 hr = IDirect3DDevice9Ex_CreateVertexShader(device, simple_vs, &shader);
1345 ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr);
1346 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1347 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1348 IDirect3DVertexShader9_Release(shader);
1350 /* Try setting invalid modes. */
1351 memset(&d3dpp, 0, sizeof(d3dpp));
1352 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1353 d3dpp.Windowed = FALSE;
1354 d3dpp.BackBufferWidth = 32;
1355 d3dpp.BackBufferHeight = 32;
1356 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1357 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1358 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1359 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1361 memset(&d3dpp, 0, sizeof(d3dpp));
1362 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1363 d3dpp.Windowed = FALSE;
1364 d3dpp.BackBufferWidth = 801;
1365 d3dpp.BackBufferHeight = 600;
1366 hr = IDirect3DDevice9Ex_Reset(device, &d3dpp);
1367 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1368 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1369 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1371 hr = IDirect3D9_GetAdapterDisplayMode(d3d9, D3DADAPTER_DEFAULT, &d3ddm);
1372 ok(SUCCEEDED(hr), "Failed to get display mode, hr %#x.\n", hr);
1374 memset(&d3dpp, 0, sizeof(d3dpp));
1375 d3dpp.Windowed = TRUE;
1376 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1377 d3dpp.BackBufferFormat = d3ddm.Format;
1378 d3dpp.EnableAutoDepthStencil = FALSE;
1379 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1381 cleanup:
1382 HeapFree(GetProcessHeap(), 0, modes);
1383 IDirect3D9_Release(d3d9);
1384 refcount = IDirect3DDevice9Ex_Release(device);
1385 ok(!refcount, "Device has %u references left.\n", refcount);
1386 DestroyWindow(window);
1389 static void test_reset_ex(void)
1391 unsigned int height, orig_height = GetSystemMetrics(SM_CYSCREEN);
1392 unsigned int width, orig_width = GetSystemMetrics(SM_CXSCREEN);
1393 unsigned int i, adapter_mode_count, mode_count = 0;
1394 D3DDISPLAYMODEEX mode, mode2, *modes;
1395 D3DDISPLAYMODEFILTER mode_filter;
1396 IDirect3DSwapChain9 *swapchain;
1397 D3DPRESENT_PARAMETERS d3dpp;
1398 IDirect3DDevice9Ex *device;
1399 IDirect3D9Ex *d3d9;
1400 DEVMODEW devmode;
1401 D3DVIEWPORT9 vp;
1402 ULONG refcount;
1403 DWORD value;
1404 HWND window;
1405 HRESULT hr;
1406 RECT rect;
1407 LONG ret;
1409 window = create_window();
1410 if (!(device = create_device(window, NULL)))
1412 skip("Failed to create a D3D device.\n");
1413 DestroyWindow(window);
1414 return;
1417 hr = IDirect3DDevice9Ex_GetDirect3D(device, (IDirect3D9 **)&d3d9);
1418 ok(SUCCEEDED(hr), "Failed to get d3d9, hr %#x.\n", hr);
1420 memset(&mode, 0, sizeof(mode));
1421 mode.Size = sizeof(mode);
1422 hr = IDirect3D9Ex_GetAdapterDisplayModeEx(d3d9, D3DADAPTER_DEFAULT, &mode, NULL);
1423 ok(SUCCEEDED(hr), "GetAdapterDisplayModeEx failed, hr %#x.\n", hr);
1424 memset(&mode_filter, 0, sizeof(mode_filter));
1425 mode_filter.Size = sizeof(mode_filter);
1426 mode_filter.Format = mode.Format;
1427 adapter_mode_count = IDirect3D9Ex_GetAdapterModeCountEx(d3d9, D3DADAPTER_DEFAULT, &mode_filter);
1428 modes = HeapAlloc(GetProcessHeap(), 0, sizeof(*modes) * adapter_mode_count);
1429 for (i = 0; i < adapter_mode_count; ++i)
1431 unsigned int j;
1433 memset(&mode2, 0, sizeof(mode));
1434 mode2.Size = sizeof(mode2);
1435 hr = IDirect3D9Ex_EnumAdapterModesEx(d3d9, D3DADAPTER_DEFAULT, &mode_filter, i, &mode2);
1436 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
1438 for (j = 0; j < mode_count; ++j)
1440 if (modes[j].Width == mode2.Width && modes[j].Height == mode2.Height)
1441 break;
1443 if (j == mode_count)
1445 modes[j] = mode2;
1446 ++mode_count;
1450 if (mode_count < 2)
1452 skip("Less than 2 modes supported.\n");
1453 goto cleanup;
1456 i = 0;
1457 if (modes[i].Width == orig_width && modes[i].Height == orig_height)
1458 ++i;
1460 memset(&d3dpp, 0, sizeof(d3dpp));
1461 d3dpp.Windowed = FALSE;
1462 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1463 d3dpp.BackBufferWidth = modes[i].Width;
1464 d3dpp.BackBufferHeight = modes[i].Height;
1465 d3dpp.BackBufferFormat = modes[i].Format;
1466 d3dpp.EnableAutoDepthStencil = TRUE;
1467 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
1468 modes[i].RefreshRate = 0;
1469 modes[i].ScanLineOrdering = 0;
1470 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1471 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1472 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1473 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1474 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1475 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1477 width = GetSystemMetrics(SM_CXSCREEN);
1478 height = GetSystemMetrics(SM_CYSCREEN);
1479 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1480 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1482 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1483 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1484 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1485 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1487 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1488 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1489 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1490 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1491 ok(vp.Width == modes[i].Width, "Got vp.Width %u, expected %u.\n", vp.Width, modes[i].Width);
1492 ok(vp.Height == modes[i].Height, "Got vp.Height %u, expected %u.\n", vp.Height, modes[i].Height);
1493 ok(vp.MinZ == 0.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1494 ok(vp.MaxZ == 1.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1496 i = 1;
1497 vp.X = 10;
1498 vp.Y = 20;
1499 vp.MinZ = 2.0f;
1500 vp.MaxZ = 3.0f;
1501 hr = IDirect3DDevice9Ex_SetViewport(device, &vp);
1502 ok(SUCCEEDED(hr), "Failed to set viewport, hr %#x.\n", hr);
1504 SetRect(&rect, 10, 20, 30, 40);
1505 hr = IDirect3DDevice9Ex_SetScissorRect(device, &rect);
1506 ok(SUCCEEDED(hr), "Failed to set scissor rect, hr %#x.\n", hr);
1508 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1509 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1510 ok(!!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1511 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1512 ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
1514 memset(&d3dpp, 0, sizeof(d3dpp));
1515 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1516 d3dpp.Windowed = FALSE;
1517 d3dpp.BackBufferWidth = modes[i].Width;
1518 d3dpp.BackBufferHeight = modes[i].Height;
1519 d3dpp.BackBufferFormat = modes[i].Format;
1520 modes[i].RefreshRate = 0;
1521 modes[i].ScanLineOrdering = 0;
1522 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1523 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1524 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1525 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1527 /* Render states are preserved in d3d9ex. */
1528 hr = IDirect3DDevice9_GetRenderState(device, D3DRS_LIGHTING, &value);
1529 ok(SUCCEEDED(hr), "Failed to get render state, hr %#x.\n", hr);
1530 ok(!value, "Got unexpected value %#x for D3DRS_LIGHTING.\n", value);
1532 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1533 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1534 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1535 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1537 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1538 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1539 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1540 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1541 ok(vp.Width == modes[i].Width, "Got vp.Width %u, expected %u.\n", vp.Width, modes[i].Width);
1542 ok(vp.Height == modes[i].Height, "Got vp.Height %u, expected %u.\n", vp.Height, modes[i].Height);
1543 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1544 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1546 width = GetSystemMetrics(SM_CXSCREEN);
1547 height = GetSystemMetrics(SM_CYSCREEN);
1548 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1549 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1551 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1552 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1553 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1554 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1555 ok(d3dpp.BackBufferWidth == modes[i].Width, "Got backbuffer width %u, expected %u.\n",
1556 d3dpp.BackBufferWidth, modes[i].Width);
1557 ok(d3dpp.BackBufferHeight == modes[i].Height, "Got backbuffer height %u, expected %u.\n",
1558 d3dpp.BackBufferHeight, modes[i].Height);
1559 IDirect3DSwapChain9_Release(swapchain);
1561 /* BackBufferWidth and BackBufferHeight have to match display mode. */
1562 memset(&d3dpp, 0, sizeof(d3dpp));
1563 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1564 d3dpp.Windowed = FALSE;
1565 d3dpp.BackBufferFormat = modes[i].Format;
1566 d3dpp.BackBufferWidth = modes[i].Width - 10;
1567 d3dpp.BackBufferHeight = modes[i].Height - 10;
1568 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1569 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1570 d3dpp.BackBufferWidth = modes[i].Width - 1;
1571 d3dpp.BackBufferHeight = modes[i].Height;
1572 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1573 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1574 d3dpp.BackBufferWidth = modes[i].Width;
1575 d3dpp.BackBufferHeight = modes[i].Height - 1;
1576 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1577 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1578 d3dpp.BackBufferWidth = 0;
1579 d3dpp.BackBufferHeight = 0;
1580 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1581 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1582 d3dpp.BackBufferWidth = modes[i].Width;
1583 d3dpp.BackBufferHeight = modes[i].Height;
1584 mode2 = modes[i];
1585 mode2.Width = 0;
1586 mode2.Height = 0;
1587 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &mode2);
1588 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1589 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1590 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1592 d3dpp.BackBufferWidth = modes[i].Width;
1593 d3dpp.BackBufferHeight = modes[i].Height;
1594 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &modes[i]);
1595 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1596 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1597 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1599 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1600 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1601 ok(rect.left == 0 && rect.top == 0 && rect.right == modes[i].Width && rect.bottom == modes[i].Height,
1602 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1604 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1605 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1606 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1607 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1608 ok(vp.Width == modes[i].Width, "Got vp.Width %u, expected %u.\n", vp.Width, modes[i].Width);
1609 ok(vp.Height == modes[i].Height, "Got vp.Height %u, expected %u.\n", vp.Height, modes[i].Height);
1610 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1611 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1613 width = GetSystemMetrics(SM_CXSCREEN);
1614 height = GetSystemMetrics(SM_CYSCREEN);
1615 ok(width == modes[i].Width, "Got screen width %u, expected %u.\n", width, modes[i].Width);
1616 ok(height == modes[i].Height, "Got screen height %u, expected %u.\n", height, modes[i].Height);
1618 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1619 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1620 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1621 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1622 ok(d3dpp.BackBufferWidth == modes[i].Width, "Got backbuffer width %u, expected %u.\n",
1623 d3dpp.BackBufferWidth, modes[i].Width);
1624 ok(d3dpp.BackBufferHeight == modes[i].Height, "Got backbuffer height %u, expected %u.\n",
1625 d3dpp.BackBufferHeight, modes[i].Height);
1626 IDirect3DSwapChain9_Release(swapchain);
1628 memset(&d3dpp, 0, sizeof(d3dpp));
1629 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1630 d3dpp.Windowed = TRUE;
1631 d3dpp.BackBufferWidth = 400;
1632 d3dpp.BackBufferHeight = 300;
1633 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1634 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1635 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1636 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1637 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1639 width = GetSystemMetrics(SM_CXSCREEN);
1640 height = GetSystemMetrics(SM_CYSCREEN);
1641 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1642 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1644 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1645 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1646 ok(rect.left == 0 && rect.top == 0 && rect.right == 400 && rect.bottom == 300,
1647 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1649 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1650 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1651 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1652 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1653 ok(vp.Width == 400, "Got unexpected vp.Width %u.\n", vp.Width);
1654 ok(vp.Height == 300, "Got unexpected vp.Height %u.\n", vp.Height);
1655 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1656 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1658 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1659 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1660 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1661 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1662 ok(d3dpp.BackBufferWidth == 400, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1663 ok(d3dpp.BackBufferHeight == 300, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1664 IDirect3DSwapChain9_Release(swapchain);
1666 memset(&devmode, 0, sizeof(devmode));
1667 devmode.dmSize = sizeof(devmode);
1668 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1669 devmode.dmPelsWidth = modes[1].Width;
1670 devmode.dmPelsHeight = modes[1].Height;
1671 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1672 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1673 width = GetSystemMetrics(SM_CXSCREEN);
1674 height = GetSystemMetrics(SM_CYSCREEN);
1675 ok(width == modes[1].Width, "Screen width is %u, expected %u.\n", width, modes[1].Width);
1676 ok(height == modes[1].Height, "Screen height is %u, expected %u.\n", height, modes[1].Height);
1678 d3dpp.BackBufferWidth = 500;
1679 d3dpp.BackBufferHeight = 400;
1680 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
1681 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, &mode);
1682 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
1683 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1684 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1685 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1686 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1688 width = GetSystemMetrics(SM_CXSCREEN);
1689 height = GetSystemMetrics(SM_CYSCREEN);
1690 ok(width == modes[1].Width, "Screen width is %u, expected %u.\n", width, modes[1].Width);
1691 ok(height == modes[1].Height, "Screen height is %u, expected %u.\n", height, modes[1].Height);
1693 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1694 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1695 ok(rect.left == 0 && rect.top == 0 && rect.right == 500 && rect.bottom == 400,
1696 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1698 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1699 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1700 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1701 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1702 ok(vp.Width == 500, "Got unexpected vp.Width %u.\n", vp.Width);
1703 ok(vp.Height == 400, "Got unexpected vp.Height %u.\n", vp.Height);
1704 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1705 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1707 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1708 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1709 memset(&d3dpp, 0, sizeof(d3dpp));
1710 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1711 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1712 ok(d3dpp.BackBufferWidth == 500, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1713 ok(d3dpp.BackBufferHeight == 400, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1714 IDirect3DSwapChain9_Release(swapchain);
1716 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
1717 devmode.dmPelsWidth = orig_width;
1718 devmode.dmPelsHeight = orig_height;
1719 ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
1720 ok(ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", ret);
1721 width = GetSystemMetrics(SM_CXSCREEN);
1722 height = GetSystemMetrics(SM_CYSCREEN);
1723 ok(width == orig_width, "Got screen width %u, expected %u.\n", width, orig_width);
1724 ok(height == orig_height, "Got screen height %u, expected %u.\n", height, orig_height);
1726 SetRect(&rect, 0, 0, 200, 150);
1727 ok(AdjustWindowRect(&rect, GetWindowLongW(window, GWL_STYLE), FALSE), "Failed to adjust window rect.\n");
1728 ok(SetWindowPos(window, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
1729 SWP_NOMOVE | SWP_NOZORDER), "Failed to set window position.\n");
1731 memset(&d3dpp, 0, sizeof(d3dpp));
1732 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
1733 d3dpp.Windowed = TRUE;
1734 d3dpp.BackBufferWidth = 0;
1735 d3dpp.BackBufferHeight = 0;
1736 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
1737 hr = IDirect3DDevice9Ex_ResetEx(device, &d3dpp, NULL);
1738 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
1739 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1740 ok(hr == D3D_OK, "Got unexpected cooperative level %#x.\n", hr);
1742 ok(d3dpp.BackBufferWidth == 200, "Got unexpected BackBufferWidth %u.\n", d3dpp.BackBufferWidth);
1743 ok(d3dpp.BackBufferHeight == 150, "Got unexpected BackBufferHeight %u.\n", d3dpp.BackBufferHeight);
1744 ok(d3dpp.BackBufferFormat == mode.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1745 d3dpp.BackBufferFormat, mode.Format);
1746 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1747 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1748 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1749 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1750 ok(!d3dpp.hDeviceWindow, "Got unexpected hDeviceWindow %p.\n", d3dpp.hDeviceWindow);
1751 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1752 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1753 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1754 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1755 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1756 d3dpp.FullScreen_RefreshRateInHz);
1757 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1759 hr = IDirect3DDevice9Ex_GetScissorRect(device, &rect);
1760 ok(SUCCEEDED(hr), "Failed to get scissor rect, hr %#x.\n", hr);
1761 ok(rect.left == 0 && rect.top == 0 && rect.right == 200 && rect.bottom == 150,
1762 "Got unexpected scissor rect %s.\n", wine_dbgstr_rect(&rect));
1764 hr = IDirect3DDevice9Ex_GetViewport(device, &vp);
1765 ok(SUCCEEDED(hr), "Failed to get viewport, hr %#x.\n", hr);
1766 ok(vp.X == 0, "Got unexpected vp.X %u.\n", vp.X);
1767 ok(vp.Y == 0, "Got unexpected vp.Y %u.\n", vp.Y);
1768 ok(vp.Width == 200, "Got unexpected vp.Width %u.\n", vp.Width);
1769 ok(vp.Height == 150, "Got unexpected vp.Height %u.\n", vp.Height);
1770 ok(vp.MinZ == 2.0f, "Got unexpected vp.MinZ %.8e.\n", vp.MinZ);
1771 ok(vp.MaxZ == 3.0f, "Got unexpected vp.MaxZ %.8e.\n", vp.MaxZ);
1773 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
1774 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x.\n", hr);
1775 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &d3dpp);
1776 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x.\n", hr);
1777 ok(d3dpp.BackBufferWidth == 200, "Got unexpected backbuffer width %u.\n", d3dpp.BackBufferWidth);
1778 ok(d3dpp.BackBufferHeight == 150, "Got unexpected backbuffer height %u.\n", d3dpp.BackBufferHeight);
1779 ok(d3dpp.BackBufferFormat == mode.Format, "Got unexpected BackBufferFormat %#x, expected %#x.\n",
1780 d3dpp.BackBufferFormat, mode.Format);
1781 ok(d3dpp.BackBufferCount == 1, "Got unexpected BackBufferCount %u.\n", d3dpp.BackBufferCount);
1782 ok(!d3dpp.MultiSampleType, "Got unexpected MultiSampleType %u.\n", d3dpp.MultiSampleType);
1783 ok(!d3dpp.MultiSampleQuality, "Got unexpected MultiSampleQuality %u.\n", d3dpp.MultiSampleQuality);
1784 ok(d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD, "Got unexpected SwapEffect %#x.\n", d3dpp.SwapEffect);
1785 ok(d3dpp.hDeviceWindow == window, "Got unexpected hDeviceWindow %p, expected %p.\n", d3dpp.hDeviceWindow, window);
1786 ok(d3dpp.Windowed, "Got unexpected Windowed %#x.\n", d3dpp.Windowed);
1787 ok(!d3dpp.EnableAutoDepthStencil, "Got unexpected EnableAutoDepthStencil %#x.\n", d3dpp.EnableAutoDepthStencil);
1788 ok(!d3dpp.AutoDepthStencilFormat, "Got unexpected AutoDepthStencilFormat %#x.\n", d3dpp.AutoDepthStencilFormat);
1789 ok(!d3dpp.Flags, "Got unexpected Flags %#x.\n", d3dpp.Flags);
1790 ok(!d3dpp.FullScreen_RefreshRateInHz, "Got unexpected FullScreen_RefreshRateInHz %u.\n",
1791 d3dpp.FullScreen_RefreshRateInHz);
1792 ok(!d3dpp.PresentationInterval, "Got unexpected PresentationInterval %#x.\n", d3dpp.PresentationInterval);
1793 IDirect3DSwapChain9_Release(swapchain);
1795 cleanup:
1796 HeapFree(GetProcessHeap(), 0, modes);
1797 IDirect3D9Ex_Release(d3d9);
1798 refcount = IDirect3DDevice9Ex_Release(device);
1799 ok(!refcount, "Device has %u references left.\n", refcount);
1800 DestroyWindow(window);
1803 static void test_reset_resources(void)
1805 IDirect3DSurface9 *surface, *rt;
1806 IDirect3DTexture9 *texture;
1807 IDirect3DDevice9Ex *device;
1808 unsigned int i;
1809 D3DCAPS9 caps;
1810 HWND window;
1811 HRESULT hr;
1812 ULONG ref;
1814 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1815 0, 0, 640, 480, 0, 0, 0, 0);
1816 if (!(device = create_device(window, NULL)))
1818 skip("Failed to create a D3D device, skipping tests.\n");
1819 goto done;
1822 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1823 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1825 hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 128, 128, D3DFMT_D24S8,
1826 D3DMULTISAMPLE_NONE, 0, TRUE, &surface, NULL);
1827 ok(SUCCEEDED(hr), "Failed to create depth/stencil surface, hr %#x.\n", hr);
1828 hr = IDirect3DDevice9_SetDepthStencilSurface(device, surface);
1829 ok(SUCCEEDED(hr), "Failed to set depth/stencil surface, hr %#x.\n", hr);
1830 IDirect3DSurface9_Release(surface);
1832 for (i = 0; i < caps.NumSimultaneousRTs; ++i)
1834 hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET,
1835 D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
1836 ok(SUCCEEDED(hr), "Failed to create render target texture %u, hr %#x.\n", i, hr);
1837 hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1838 ok(SUCCEEDED(hr), "Failed to get surface %u, hr %#x.\n", i, hr);
1839 IDirect3DTexture9_Release(texture);
1840 hr = IDirect3DDevice9_SetRenderTarget(device, i, surface);
1841 ok(SUCCEEDED(hr), "Failed to set render target surface %u, hr %#x.\n", i, hr);
1842 IDirect3DSurface9_Release(surface);
1845 hr = reset_device(device, NULL);
1846 ok(SUCCEEDED(hr), "Failed to reset device.\n");
1848 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &rt);
1849 ok(SUCCEEDED(hr), "Failed to get back buffer, hr %#x.\n", hr);
1850 hr = IDirect3DDevice9_GetRenderTarget(device, 0, &surface);
1851 ok(SUCCEEDED(hr), "Failed to get render target surface, hr %#x.\n", hr);
1852 ok(surface == rt, "Got unexpected surface %p for render target.\n", surface);
1853 IDirect3DSurface9_Release(surface);
1854 IDirect3DSurface9_Release(rt);
1856 for (i = 1; i < caps.NumSimultaneousRTs; ++i)
1858 hr = IDirect3DDevice9_GetRenderTarget(device, i, &surface);
1859 ok(hr == D3DERR_NOTFOUND, "Got unexpected hr %#x.\n", hr);
1862 ref = IDirect3DDevice9_Release(device);
1863 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1865 done:
1866 DestroyWindow(window);
1869 static void test_vidmem_accounting(void)
1871 IDirect3DDevice9Ex *device;
1872 unsigned int i;
1873 HWND window;
1874 HRESULT hr = D3D_OK;
1875 ULONG ref;
1876 UINT vidmem_start, vidmem_end;
1877 INT diff;
1878 IDirect3DTexture9 *textures[20];
1880 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1881 0, 0, 640, 480, 0, 0, 0, 0);
1882 if (!(device = create_device(window, NULL)))
1884 skip("Failed to create a D3D device, skipping tests.\n");
1885 goto done;
1888 vidmem_start = IDirect3DDevice9_GetAvailableTextureMem(device);
1889 memset(textures, 0, sizeof(textures));
1890 for (i = 0; i < 20 && SUCCEEDED(hr); i++)
1892 hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1, D3DUSAGE_RENDERTARGET,
1893 D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &textures[i], NULL);
1894 /* No D3DERR_OUTOFVIDEOMEMORY in d3d9ex */
1895 ok(SUCCEEDED(hr) || hr == E_OUTOFMEMORY, "Failed to create texture, hr %#x.\n", hr);
1897 vidmem_end = IDirect3DDevice9_GetAvailableTextureMem(device);
1899 diff = vidmem_start - vidmem_end;
1900 diff = abs(diff);
1901 ok(diff < 1024 * 1024, "Expected a video memory difference of less than 1 MB, got %u MB.\n",
1902 diff / 1024 / 1024);
1904 for (i = 0; i < 20; i++)
1906 if (textures[i])
1907 IDirect3DTexture9_Release(textures[i]);
1910 ref = IDirect3DDevice9_Release(device);
1911 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1913 done:
1914 DestroyWindow(window);
1917 static void test_user_memory_getdc(void)
1919 IDirect3DDevice9Ex *device;
1920 HBITMAP bitmap;
1921 DIBSECTION dib;
1922 HWND window;
1923 HRESULT hr;
1924 ULONG ref;
1925 int size;
1926 IDirect3DSurface9 *surface;
1927 DWORD *data;
1928 HDC dc;
1930 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1931 0, 0, 640, 480, 0, 0, 0, 0);
1932 if (!(device = create_device(window, NULL)))
1934 skip("Failed to create a D3D device, skipping tests.\n");
1935 goto done;
1938 data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) * 16 * 16);
1939 memset(data, 0xaa, sizeof(*data) * 16 * 16);
1940 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 16, 16,
1941 D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, (HANDLE *)&data);
1942 ok(SUCCEEDED(hr), "Failed to create surface, hr %#x.\n", hr);
1944 hr = IDirect3DSurface9_GetDC(surface, &dc);
1945 ok(SUCCEEDED(hr), "Failed to get dc, hr %#x.\n", hr);
1946 bitmap = GetCurrentObject(dc, OBJ_BITMAP);
1947 ok(!!bitmap, "Failed to get bitmap.\n");
1948 size = GetObjectA(bitmap, sizeof(dib), &dib);
1949 ok(size == sizeof(dib), "Got unexpected size %d.\n", size);
1950 ok(dib.dsBm.bmBits == data, "Got unexpected bits %p, expected %p.\n", dib.dsBm.bmBits, data);
1951 BitBlt(dc, 0, 0, 16, 8, NULL, 0, 0, WHITENESS);
1952 BitBlt(dc, 0, 8, 16, 8, NULL, 0, 0, BLACKNESS);
1953 hr = IDirect3DSurface9_ReleaseDC(surface, dc);
1954 ok(SUCCEEDED(hr), "Failed to release dc, hr %#x.\n", hr);
1956 ok(data[0] == 0xffffffff, "Expected color 0xffffffff, got %#x.\n", data[0]);
1957 ok(data[8 * 16] == 0x00000000, "Expected color 0x00000000, got %#x.\n", data[8 * 16]);
1959 IDirect3DSurface9_Release(surface);
1960 HeapFree(GetProcessHeap(), 0, data);
1962 ref = IDirect3DDevice9_Release(device);
1963 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
1965 done:
1966 DestroyWindow(window);
1969 static void test_lost_device(void)
1971 IDirect3DDevice9Ex *device;
1972 ULONG refcount;
1973 HWND window;
1974 HRESULT hr;
1975 BOOL ret;
1976 struct device_desc desc;
1978 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
1979 0, 0, 640, 480, NULL, NULL, NULL, NULL);
1980 desc.device_window = window;
1981 desc.width = 640;
1982 desc.height = 480;
1983 desc.flags = CREATE_DEVICE_FULLSCREEN;
1984 if (!(device = create_device(window, &desc)))
1986 skip("Failed to create a D3D device, skipping tests.\n");
1987 goto done;
1990 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
1991 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1992 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
1993 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1994 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
1995 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1996 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
1997 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
1998 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
1999 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2001 ret = SetForegroundWindow(GetDesktopWindow());
2002 ok(ret, "Failed to set foreground window.\n");
2003 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2004 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2005 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2006 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2007 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2008 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2009 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2010 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2011 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2012 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2014 ret = SetForegroundWindow(window);
2015 ok(ret, "Failed to set foreground window.\n");
2016 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2017 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2018 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2019 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2020 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2021 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2022 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2023 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2024 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2025 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2027 desc.width = 1024;
2028 desc.height = 768;
2029 hr = reset_device(device, &desc);
2030 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2031 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2032 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2033 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2034 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2035 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2036 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2037 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2038 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2039 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2040 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2042 desc.flags = 0;
2043 hr = reset_device(device, &desc);
2044 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2045 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2046 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2047 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2048 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#x.\n", hr);
2049 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2050 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#x.\n", hr);
2051 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2052 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#x.\n", hr);
2053 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2054 ok(hr == S_PRESENT_MODE_CHANGED || hr == D3D_OK /* Win10 */, "Got unexpected hr %#x.\n", hr);
2056 hr = reset_device(device, &desc);
2057 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2058 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2059 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2060 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2061 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2062 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2063 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2064 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2065 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2066 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2067 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2069 ret = SetForegroundWindow(GetDesktopWindow());
2070 ok(ret, "Failed to set foreground window.\n");
2071 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2072 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2073 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2074 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2075 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2076 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2077 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2078 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2079 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2080 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2082 ret = SetForegroundWindow(window);
2083 ok(ret, "Failed to set foreground window.\n");
2084 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2085 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2086 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2087 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2088 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2089 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2090 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2091 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2092 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2093 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2095 desc.flags = CREATE_DEVICE_FULLSCREEN;
2096 hr = reset_device(device, &desc);
2097 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2098 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2099 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2100 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2101 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2102 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2103 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2104 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2105 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2106 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2107 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2109 ret = SetForegroundWindow(GetDesktopWindow());
2110 ok(ret, "Failed to set foreground window.\n");
2111 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2112 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2113 hr = reset_device(device, &desc);
2114 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2115 hr = IDirect3DDevice9Ex_TestCooperativeLevel(device);
2116 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2117 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2118 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2119 hr = IDirect3DDevice9Ex_PresentEx(device, NULL, NULL, NULL, NULL, 0);
2120 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2121 hr = IDirect3DDevice9Ex_CheckDeviceState(device, window);
2122 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2123 hr = IDirect3DDevice9Ex_CheckDeviceState(device, NULL);
2124 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x.\n", hr);
2126 refcount = IDirect3DDevice9Ex_Release(device);
2127 ok(!refcount, "Device has %u references left.\n", refcount);
2128 done:
2129 DestroyWindow(window);
2132 static void test_unsupported_shaders(void)
2134 static const DWORD simple_vs[] =
2136 0xfffe0101, /* vs_1_1 */
2137 0x0000001f, 0x80000000, 0x900f0000, /* dcl_position0 v0 */
2138 0x00000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
2139 0x0000ffff, /* end */
2141 static const DWORD simple_ps[] =
2143 0xffff0101, /* ps_1_1 */
2144 0x00000001, 0x800f0000, 0x90e40000, /* mul r0, t0, r0 */
2145 0x0000ffff, /* end */
2147 static const DWORD vs_3_0[] =
2149 0xfffe0300, /* vs_3_0 */
2150 0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
2151 0x0200001f, 0x80000000, 0xe00f0000, /* dcl_position o0 */
2152 0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
2153 0x0000ffff, /* end */
2156 #if 0
2157 float4 main(const float4 color : COLOR) : SV_TARGET
2159 float4 o;
2161 o = color;
2163 return o;
2165 #endif
2166 static const DWORD ps_4_0[] =
2168 0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac, 0x00000005,
2169 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452, 0x00000050, 0x00000000,
2170 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f,
2171 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e,
2172 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020,
2173 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f,
2174 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
2175 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, 0x0000000e,
2176 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, 0x001020f2,
2177 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453, 0x00000074, 0x00000002, 0x00000000,
2178 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000,
2179 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2180 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
2181 0x00000000, 0x00000000, 0x00000000,
2183 #if 0
2184 vs_1_1
2185 dcl_position v0
2186 def c255, 1.0, 1.0, 1.0, 1.0
2187 add r0, v0, c255
2188 mov oPos, r0
2189 #endif
2190 static const DWORD vs_1_255[] =
2192 0xfffe0101,
2193 0x0000001f, 0x80000000, 0x900f0000,
2194 0x00000051, 0xa00f00ff, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2195 0x00000002, 0x800f0000, 0x90e40000, 0xa0e400ff,
2196 0x00000001, 0xc00f0000, 0x80e40000,
2197 0x0000ffff
2199 #if 0
2200 vs_1_1
2201 dcl_position v0
2202 def c256, 1.0, 1.0, 1.0, 1.0
2203 add r0, v0, c256
2204 mov oPos, r0
2205 #endif
2206 static const DWORD vs_1_256[] =
2208 0xfffe0101,
2209 0x0000001f, 0x80000000, 0x900f0000,
2210 0x00000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2211 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40100,
2212 0x00000001, 0xc00f0000, 0x80e40000,
2213 0x0000ffff
2215 #if 0
2216 vs_3_0
2217 dcl_position v0
2218 dcl_position o0
2219 def c256, 1.0, 1.0, 1.0, 1.0
2220 add r0, v0, c256
2221 mov o0, r0
2222 #endif
2223 static const DWORD vs_3_256[] =
2225 0xfffe0300,
2226 0x0200001f, 0x80000000, 0x900f0000,
2227 0x0200001f, 0x80000000, 0xe00f0000,
2228 0x05000051, 0xa00f0100, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2229 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40100,
2230 0x02000001, 0xe00f0000, 0x80e40000,
2231 0x0000ffff
2233 #if 0
2234 /* This shader source generates syntax errors with the native shader assembler
2235 * due to the constant register index values.
2236 * The bytecode was modified by hand to use the intended values. */
2237 vs_3_0
2238 dcl_position v0
2239 dcl_position o0
2240 defi i16, 1, 1, 1, 1
2241 rep i16
2242 add r0, r0, v0
2243 endrep
2244 mov o0, r0
2245 #endif
2246 static const DWORD vs_3_i16[] =
2248 0xfffe0300,
2249 0x0200001f, 0x80000000, 0x900f0000,
2250 0x0200001f, 0x80000000, 0xe00f0000,
2251 0x05000030, 0xf00f0010, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
2252 0x01000026, 0xf0e40010,
2253 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2254 0x00000027,
2255 0x02000001, 0xe00f0000, 0x80e40000,
2256 0x0000ffff
2258 #if 0
2259 /* This shader source generates syntax errors with the native shader assembler
2260 * due to the constant register index values.
2261 * The bytecode was modified by hand to use the intended values. */
2262 vs_3_0
2263 dcl_position v0
2264 dcl_position o0
2265 defb b16, true
2266 mov r0, v0
2267 if b16
2268 add r0, r0, v0
2269 endif
2270 mov o0, r0
2271 #endif
2272 static const DWORD vs_3_b16[] =
2274 0xfffe0300,
2275 0x0200001f, 0x80000000, 0x900f0000,
2276 0x0200001f, 0x80000000, 0xe00f0000,
2277 0x0200002f, 0xe00f0810, 0x00000001,
2278 0x02000001, 0x800f0000, 0x90e40000,
2279 0x01000028, 0xe0e40810,
2280 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2281 0x0000002b,
2282 0x02000001, 0xe00f0000, 0x80e40000,
2283 0x0000ffff
2285 #if 0
2286 /* This shader source generates syntax errors with the native shader assembler
2287 * due to the constant register index values.
2288 * The bytecode was modified by hand to use the intended values. */
2289 ps_1_1
2290 def c8, 1.0, 1.0, 1.0, 1.0
2291 add r0, v0, c8
2292 #endif
2293 static const DWORD ps_1_8[] =
2295 0xffff0101,
2296 0x00000051, 0xa00f0008, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2297 0x00000002, 0x800f0000, 0x90e40000, 0xa0e40008,
2298 0x0000ffff
2300 #if 0
2301 /* This shader source generates syntax errors with the native shader assembler
2302 * due to the constant register index values.
2303 * The bytecode was modified by hand to use the intended values. */
2304 ps_2_0
2305 def c32, 1.0, 1.0, 1.0, 1.0
2306 add oC0, v0, c32
2307 #endif
2308 static const DWORD ps_2_32[] =
2310 0xffff0200,
2311 0x05000051, 0xa00f0020, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2312 0x03000002, 0x800f0000, 0x90e40000, 0xa0e40020,
2313 0x0000ffff
2315 #if 0
2316 /* This shader source generates syntax errors with the native shader assembler
2317 * due to the constant register index values.
2318 * The bytecode was modified by hand to use the intended values. */
2319 ps_3_0
2320 dcl_color0 v0
2321 def c224, 1.0, 1.0, 1.0, 1.0
2322 add oC0, v0, c224
2323 #endif
2324 static const DWORD ps_3_224[] =
2326 0xffff0300,
2327 0x0200001f, 0x8000000a, 0x900f0000,
2328 0x05000051, 0xa00f00e0, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
2329 0x03000002, 0x800f0800, 0x90e40000, 0xa0e400e0,
2330 0x0000ffff
2332 #if 0
2333 /* This shader source generates syntax errors with the native shader assembler
2334 * due to the constant register index values.
2335 * The bytecode was modified by hand to use the intended values. */
2336 ps_2_0
2337 defb b0, true
2338 defi i0, 1, 1, 1, 1
2339 rep i0
2340 if b0
2341 add r0, r0, v0
2342 endif
2343 endrep
2344 mov oC0, r0
2345 #endif
2346 static const DWORD ps_2_0_boolint[] =
2348 0xffff0200,
2349 0x0200002f, 0xe00f0800, 0x00000001,
2350 0x05000030, 0xf00f0000, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
2351 0x01000026, 0xf0e40000,
2352 0x01000028, 0xe0e40800,
2353 0x03000002, 0x800f0000, 0x80e40000, 0x90e40000,
2354 0x0000002b,
2355 0x00000027,
2356 0x02000001, 0x800f0800, 0x80e40000,
2357 0x0000ffff
2360 IDirect3DVertexShader9 *vs = NULL;
2361 IDirect3DPixelShader9 *ps = NULL;
2362 IDirect3DDevice9Ex *device;
2363 ULONG refcount;
2364 D3DCAPS9 caps;
2365 HWND window;
2366 HRESULT hr;
2368 window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW,
2369 0, 0, 640, 480, 0, 0, 0, 0);
2370 if (!(device = create_device(window, NULL)))
2372 skip("Failed to create a D3D device, skipping tests.\n");
2373 DestroyWindow(window);
2374 return;
2377 hr = IDirect3DDevice9Ex_CreateVertexShader(device, simple_ps, &vs);
2378 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2379 hr = IDirect3DDevice9Ex_CreatePixelShader(device, simple_vs, &ps);
2380 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2381 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_4_0, &ps);
2382 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2384 hr = IDirect3DDevice9Ex_GetDeviceCaps(device, &caps);
2385 ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
2387 if (caps.VertexShaderVersion < D3DVS_VERSION(3, 0))
2389 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_0, &vs);
2390 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2391 if (caps.VertexShaderVersion <= D3DVS_VERSION(1, 1) && caps.MaxVertexShaderConst < 256)
2393 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_255, &vs);
2394 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2396 else
2398 skip("GPU supports SM2+, skipping SM1 test.\n");
2401 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
2403 else
2405 skip("This GPU supports SM3, skipping unsupported shader test.\n");
2407 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_255, &vs);
2408 ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
2409 IDirect3DVertexShader9_Release(vs);
2410 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_1_256, &vs);
2411 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2412 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_256, &vs);
2413 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2414 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_i16, &vs);
2415 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2416 hr = IDirect3DDevice9Ex_CreateVertexShader(device, vs_3_b16, &vs);
2417 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2420 if (caps.PixelShaderVersion < D3DPS_VERSION(3, 0))
2422 skip("This GPU doesn't support SM3, skipping test with shader using unsupported constants.\n");
2423 goto cleanup;
2425 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_1_8, &ps);
2426 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2427 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_2_32, &ps);
2428 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2429 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_3_224, &ps);
2430 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2431 hr = IDirect3DDevice9Ex_CreatePixelShader(device, ps_2_0_boolint, &ps);
2432 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
2433 if (ps)
2434 IDirect3DPixelShader9_Release(ps);
2436 cleanup:
2437 refcount = IDirect3DDevice9Ex_Release(device);
2438 ok(!refcount, "Device has %u references left.\n", refcount);
2439 DestroyWindow(window);
2442 static HWND filter_messages;
2444 enum message_window
2446 DEVICE_WINDOW,
2447 FOCUS_WINDOW,
2450 struct message
2452 UINT message;
2453 enum message_window window;
2454 BOOL check_wparam;
2455 WPARAM expect_wparam;
2458 static const struct message *expect_messages;
2459 static HWND device_window, focus_window;
2460 static LONG windowposchanged_received, syscommand_received;
2462 struct wndproc_thread_param
2464 HWND dummy_window;
2465 HANDLE window_created;
2466 HANDLE test_finished;
2467 BOOL running_in_foreground;
2470 static LRESULT CALLBACK test_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
2472 if (filter_messages && filter_messages == hwnd)
2474 if (message != WM_DISPLAYCHANGE && message != WM_IME_NOTIFY)
2475 todo_wine ok(0, "Received unexpected message %#x for window %p.\n", message, hwnd);
2478 if (expect_messages)
2480 HWND w;
2482 switch (expect_messages->window)
2484 case DEVICE_WINDOW:
2485 w = device_window;
2486 break;
2488 case FOCUS_WINDOW:
2489 w = focus_window;
2490 break;
2492 default:
2493 w = NULL;
2494 break;
2497 if (hwnd == w && expect_messages->message == message)
2499 if (expect_messages->check_wparam)
2500 ok(wparam == expect_messages->expect_wparam,
2501 "Got unexpected wparam %lx for message %x, expected %lx.\n",
2502 wparam, message, expect_messages->expect_wparam);
2504 ++expect_messages;
2508 /* KDE randomly does something with the hidden window during the
2509 * mode change that sometimes generates a WM_WINDOWPOSCHANGING
2510 * message. A WM_WINDOWPOSCHANGED message is not generated, so
2511 * just flag WM_WINDOWPOSCHANGED as bad. */
2512 if (message == WM_WINDOWPOSCHANGED)
2513 InterlockedIncrement(&windowposchanged_received);
2514 else if (message == WM_SYSCOMMAND)
2515 InterlockedIncrement(&syscommand_received);
2517 return DefWindowProcA(hwnd, message, wparam, lparam);
2520 static DWORD WINAPI wndproc_thread(void *param)
2522 struct wndproc_thread_param *p = param;
2523 DWORD res;
2524 BOOL ret;
2526 p->dummy_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2527 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
2528 registry_mode.dmPelsHeight, 0, 0, 0, 0);
2529 p->running_in_foreground = SetForegroundWindow(p->dummy_window);
2531 ret = SetEvent(p->window_created);
2532 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2534 for (;;)
2536 MSG msg;
2538 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2539 DispatchMessageA(&msg);
2540 res = WaitForSingleObject(p->test_finished, 100);
2541 if (res == WAIT_OBJECT_0)
2542 break;
2543 if (res != WAIT_TIMEOUT)
2545 ok(0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2546 break;
2550 DestroyWindow(p->dummy_window);
2552 return 0;
2555 static void test_wndproc(void)
2557 struct wndproc_thread_param thread_params;
2558 struct device_desc device_desc;
2559 IDirect3DDevice9Ex *device;
2560 WNDCLASSA wc = {0};
2561 HANDLE thread;
2562 LONG_PTR proc;
2563 ULONG ref;
2564 DWORD res, tid;
2565 HWND tmp;
2566 UINT i, adapter_mode_count;
2567 HRESULT hr;
2568 D3DDISPLAYMODE d3ddm;
2569 DWORD d3d_width = 0, d3d_height = 0, user32_width = 0, user32_height = 0;
2570 DEVMODEW devmode;
2571 LONG change_ret;
2572 BOOL ret;
2573 IDirect3D9Ex *d3d9ex;
2575 static const struct message create_messages[] =
2577 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2578 /* Do not test wparam here. If device creation succeeds,
2579 * wparam is WA_ACTIVE. If device creation fails (testbot)
2580 * wparam is set to WA_INACTIVE on some Windows versions. */
2581 {WM_ACTIVATE, FOCUS_WINDOW, FALSE, 0},
2582 {WM_SETFOCUS, FOCUS_WINDOW, FALSE, 0},
2583 {0, 0, FALSE, 0},
2585 static const struct message focus_loss_messages[] =
2587 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2588 * not reliable on X11 WMs. When the window focus follows the
2589 * mouse pointer the message is not sent.
2590 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2591 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2592 /* WM_DISPLAYCHANGE is sent to the focus window too, but the order is
2593 * not deterministic. */
2594 {WM_WINDOWPOSCHANGING, DEVICE_WINDOW, FALSE, 0},
2595 /* Windows sends WM_ACTIVATE to the device window, indicating that
2596 * SW_SHOWMINIMIZED is used instead of SW_MINIMIZE. Yet afterwards
2597 * the foreground and focus window are NULL. On Wine SW_SHOWMINIMIZED
2598 * leaves the device window active, breaking re-activation in the
2599 * lost device test.
2600 * {WM_ACTIVATE, DEVICE_WINDOW, TRUE, 0x200000 | WA_ACTIVE}, */
2601 {WM_WINDOWPOSCHANGED, DEVICE_WINDOW, FALSE, 0},
2602 {WM_SIZE, DEVICE_WINDOW, TRUE, SIZE_MINIMIZED},
2603 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2604 /* WM_ACTIVATEAPP is sent to the device window too, but the order is
2605 * not deterministic. It may be sent after the focus window handling
2606 * or before. */
2607 {0, 0, FALSE, 0},
2609 static const struct message focus_loss_messages_nowc[] =
2611 /* WM_ACTIVATE (wparam = WA_INACTIVE) is sent on Windows. It is
2612 * not reliable on X11 WMs. When the window focus follows the
2613 * mouse pointer the message is not sent.
2614 * {WM_ACTIVATE, FOCUS_WINDOW, TRUE, WA_INACTIVE}, */
2615 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2616 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2617 {0, 0, FALSE, 0},
2619 static const struct message focus_loss_messages_hidden[] =
2621 {WM_DISPLAYCHANGE, DEVICE_WINDOW, FALSE, 0},
2622 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2623 {0, 0, FALSE, 0},
2625 static const struct message focus_loss_messages_filtered[] =
2627 /* WM_ACTIVATE is delivered to the window proc because it is
2628 * generated by SetForegroundWindow before the d3d routine
2629 * starts it work. Don't check for it due to focus-follows-mouse
2630 * WMs though. */
2631 {WM_DISPLAYCHANGE, FOCUS_WINDOW, FALSE, 0},
2632 {WM_ACTIVATEAPP, FOCUS_WINDOW, TRUE, FALSE},
2633 {0, 0, FALSE, 0},
2635 static const struct message sc_restore_messages[] =
2637 /* WM_SYSCOMMAND is delivered only once, after d3d has already
2638 * processed it. Our wndproc has no way to prevent d3d from
2639 * handling the message. The second DefWindowProc call done by
2640 * our wndproc doesn't do any changes to the window because it
2641 * is already restored due to d3d's handling. */
2642 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2643 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2644 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_RESTORED},
2645 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_RESTORE},
2646 {0, 0, FALSE, 0},
2648 static const struct message sc_minimize_messages[] =
2650 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MINIMIZE},
2651 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2652 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2653 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2654 {WM_SIZE, FOCUS_WINDOW, TRUE, SIZE_MINIMIZED},
2655 {0, 0, FALSE, 0},
2657 static const struct message sc_maximize_messages[] =
2659 {WM_SYSCOMMAND, FOCUS_WINDOW, TRUE, SC_MAXIMIZE},
2660 {WM_WINDOWPOSCHANGING, FOCUS_WINDOW, FALSE, 0},
2661 {WM_WINDOWPOSCHANGED, FOCUS_WINDOW, FALSE, 0},
2662 {WM_MOVE, FOCUS_WINDOW, FALSE, 0},
2663 /* WM_SIZE(SIZE_MAXIMIZED) is unreliable on native. */
2664 {0, 0, FALSE, 0},
2666 static const struct
2668 DWORD create_flags;
2669 const struct message *focus_loss_messages;
2670 BOOL iconic;
2672 tests[] =
2674 {0, focus_loss_messages, TRUE},
2675 {CREATE_DEVICE_NOWINDOWCHANGES, focus_loss_messages_nowc, FALSE},
2678 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
2679 if (FAILED(hr))
2681 skip("Direct3D9Ex is not available (%#x)\n", hr);
2682 return;
2685 adapter_mode_count = IDirect3D9Ex_GetAdapterModeCount(d3d9ex, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
2686 for (i = 0; i < adapter_mode_count; ++i)
2688 hr = IDirect3D9Ex_EnumAdapterModes(d3d9ex, D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddm);
2689 ok(SUCCEEDED(hr), "Failed to enumerate display mode, hr %#x.\n", hr);
2691 if (d3ddm.Width == registry_mode.dmPelsWidth && d3ddm.Height == registry_mode.dmPelsHeight)
2692 continue;
2693 /* The r200 driver on Windows XP enumerates modes like 320x200 and 320x240 but
2694 * refuses to create a device at these sizes. */
2695 if (d3ddm.Width < 640 || d3ddm.Height < 480)
2696 continue;
2698 if (!user32_width)
2700 user32_width = d3ddm.Width;
2701 user32_height = d3ddm.Height;
2702 continue;
2705 /* Make sure the d3d mode is smaller in width or height and at most
2706 * equal in the other dimension than the mode passed to
2707 * ChangeDisplaySettings. Otherwise Windows shrinks the window to
2708 * the ChangeDisplaySettings parameters + 12. */
2709 if (d3ddm.Width == user32_width && d3ddm.Height == user32_height)
2710 continue;
2711 if (d3ddm.Width <= user32_width && d3ddm.Height <= user32_height)
2713 d3d_width = d3ddm.Width;
2714 d3d_height = d3ddm.Height;
2715 break;
2717 if (user32_width <= d3ddm.Width && user32_height <= d3ddm.Height)
2719 d3d_width = user32_width;
2720 d3d_height = user32_height;
2721 user32_width = d3ddm.Width;
2722 user32_height = d3ddm.Height;
2723 break;
2727 IDirect3D9Ex_Release(d3d9ex);
2729 if (!d3d_width)
2731 skip("Could not find adequate modes, skipping mode tests.\n");
2732 return;
2735 wc.lpfnWndProc = test_proc;
2736 wc.lpszClassName = "d3d9_test_wndproc_wc";
2737 ok(RegisterClassA(&wc), "Failed to register window class.\n");
2739 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
2740 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2741 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
2742 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2744 memset(&devmode, 0, sizeof(devmode));
2745 devmode.dmSize = sizeof(devmode);
2747 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
2749 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2750 devmode.dmPelsWidth = user32_width;
2751 devmode.dmPelsHeight = user32_height;
2752 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2753 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2755 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2756 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2757 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
2758 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, user32_width, user32_height, 0, 0, 0, 0);
2759 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
2760 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2762 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2763 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2765 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2766 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2767 (LONG_PTR)test_proc, proc);
2768 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2769 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2770 (LONG_PTR)test_proc, proc);
2772 trace("device_window %p, focus_window %p, dummy_window %p.\n",
2773 device_window, focus_window, thread_params.dummy_window);
2775 tmp = GetFocus();
2776 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
2777 if (thread_params.running_in_foreground)
2779 tmp = GetForegroundWindow();
2780 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
2781 thread_params.dummy_window, tmp);
2783 else
2784 skip("Not running in foreground, skip foreground window test\n");
2786 flush_events();
2788 expect_messages = create_messages;
2790 device_desc.device_window = device_window;
2791 device_desc.width = d3d_width;
2792 device_desc.height = d3d_height;
2793 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].create_flags;
2794 if (!(device = create_device(focus_window, &device_desc)))
2796 skip("Failed to create a D3D device, skipping tests.\n");
2797 goto done;
2800 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2801 expect_messages->message, expect_messages->window, i);
2802 expect_messages = NULL;
2804 if (0) /* Disabled until we can make this work in a reliable way on Wine. */
2806 tmp = GetFocus();
2807 ok(tmp == focus_window, "Expected focus %p, got %p.\n", focus_window, tmp);
2808 tmp = GetForegroundWindow();
2809 ok(tmp == focus_window, "Expected foreground window %p, got %p.\n", focus_window, tmp);
2811 SetForegroundWindow(focus_window);
2812 flush_events();
2814 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
2815 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
2816 (LONG_PTR)test_proc, proc);
2818 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2819 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n",
2820 (LONG_PTR)test_proc);
2822 /* Change the mode while the device is in use and then drop focus. */
2823 devmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
2824 devmode.dmPelsWidth = user32_width;
2825 devmode.dmPelsHeight = user32_height;
2826 change_ret = ChangeDisplaySettingsW(&devmode, CDS_FULLSCREEN);
2827 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x, i=%u.\n", change_ret, i);
2829 /* Native needs a present call to pick up the mode change. */
2830 hr = IDirect3DDevice9Ex_Present(device, NULL, NULL, NULL, NULL);
2831 todo_wine ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x, i=%u.\n", hr, i);
2832 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2833 todo_wine ok(hr == S_PRESENT_MODE_CHANGED, "Got unexpected hr %#x, i=%u.\n", hr, i);
2835 expect_messages = tests[i].focus_loss_messages;
2836 /* SetForegroundWindow is a poor replacement for the user pressing alt-tab or
2837 * manually changing the focus. It generates the same messages, but the task
2838 * bar still shows the previous foreground window as active, and the window has
2839 * an inactive titlebar if reactivated with SetForegroundWindow. Reactivating
2840 * the device is difficult, see below. */
2841 SetForegroundWindow(GetDesktopWindow());
2842 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2843 expect_messages->message, expect_messages->window, i);
2844 expect_messages = NULL;
2845 tmp = GetFocus();
2846 ok(tmp != device_window, "The device window is active, i=%u.\n", i);
2847 ok(tmp != focus_window, "The focus window is active, i=%u.\n", i);
2849 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2850 ok(hr == S_PRESENT_OCCLUDED, "Got unexpected hr %#x, i=%u.\n", hr, i);
2852 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2853 ok(ret, "Failed to get display mode.\n");
2854 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth
2855 && devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect screen size %ux%u.\n",
2856 devmode.dmPelsWidth, devmode.dmPelsHeight);
2858 /* In d3d9ex the device and focus windows have to be minimized and restored,
2859 * otherwise native does not notice that focus has been restored. This is
2860 * independent of D3DCREATE_NOWINDOWCHANGES. */
2861 ShowWindow(device_window, SW_MINIMIZE);
2862 ShowWindow(device_window, SW_RESTORE);
2864 /* Reactivation messages like in d3d8/9 are random in native d3d9ex.
2865 * Sometimes they are sent, sometimes they are not (tested on Vista
2866 * and Windows 7). The minimizing and restoring of the device window
2867 * may have something to do with this, but if the messages are sent,
2868 * they are generated by the 3 calls below. */
2869 ShowWindow(focus_window, SW_MINIMIZE);
2870 ShowWindow(focus_window, SW_RESTORE);
2871 /* Set focus twice to make KDE and fvwm in focus-follows-mouse mode happy. */
2872 SetForegroundWindow(focus_window);
2873 flush_events();
2874 SetForegroundWindow(focus_window);
2875 flush_events();
2877 /* Calling Reset is not necessary in d3d9ex. */
2878 hr = IDirect3DDevice9Ex_CheckDeviceState(device, device_window);
2879 ok(hr == S_OK, "Got unexpected hr %#x, i=%u.\n", hr, i);
2881 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2882 ok(ret, "Failed to get display mode.\n");
2883 ok(devmode.dmPelsWidth == d3d_width
2884 && devmode.dmPelsHeight == d3d_height, "Got unexpect screen size %ux%u.\n",
2885 devmode.dmPelsWidth, devmode.dmPelsHeight);
2887 hr = reset_device(device, &device_desc);
2888 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
2890 ShowWindow(device_window, SW_HIDE);
2891 flush_events();
2893 expect_messages = focus_loss_messages_hidden;
2894 windowposchanged_received = 0;
2895 SetForegroundWindow(GetDesktopWindow());
2896 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2897 expect_messages->message, expect_messages->window, i);
2898 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
2899 expect_messages = NULL;
2900 flush_events();
2902 ret = EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &devmode);
2903 ok(ret, "Failed to get display mode.\n");
2904 ok(devmode.dmPelsWidth == registry_mode.dmPelsWidth, "Got unexpect width %u.\n", devmode.dmPelsWidth);
2905 ok(devmode.dmPelsHeight == registry_mode.dmPelsHeight, "Got unexpect height %u.\n", devmode.dmPelsHeight);
2907 /* SW_SHOWMINNOACTIVE is needed to make FVWM happy. SW_SHOWNOACTIVATE is needed to make windows
2908 * send SIZE_RESTORED after ShowWindow(SW_SHOWMINNOACTIVE). */
2909 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
2910 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
2911 flush_events();
2913 syscommand_received = 0;
2914 expect_messages = sc_restore_messages;
2915 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
2916 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2917 expect_messages->message, expect_messages->window, i);
2918 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
2919 expect_messages = NULL;
2920 flush_events();
2922 expect_messages = sc_minimize_messages;
2923 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
2924 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2925 expect_messages->message, expect_messages->window, i);
2926 expect_messages = NULL;
2927 flush_events();
2929 expect_messages = sc_maximize_messages;
2930 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
2931 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2932 expect_messages->message, expect_messages->window, i);
2933 expect_messages = NULL;
2934 flush_events();
2936 SetForegroundWindow(GetDesktopWindow());
2937 ShowWindow(device_window, SW_MINIMIZE);
2938 ShowWindow(device_window, SW_RESTORE);
2939 ShowWindow(focus_window, SW_MINIMIZE);
2940 ShowWindow(focus_window, SW_RESTORE);
2941 SetForegroundWindow(focus_window);
2942 flush_events();
2944 filter_messages = focus_window;
2945 ref = IDirect3DDevice9Ex_Release(device);
2946 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
2948 /* Fix up the mode until Wine's device release behavior is fixed. */
2949 change_ret = ChangeDisplaySettingsW(NULL, CDS_FULLSCREEN);
2950 ok(change_ret == DISP_CHANGE_SUCCESSFUL, "Failed to change display mode, ret %#x.\n", change_ret);
2952 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
2953 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx, i=%u.\n",
2954 (LONG_PTR)test_proc, proc, i);
2956 /* Hide the device window. It prevents WM_ACTIVATEAPP messages from being sent
2957 * on native in the test below. It isn't needed anyways. Creating the third
2958 * device will show it again. */
2959 filter_messages = NULL;
2960 ShowWindow(device_window, SW_HIDE);
2961 /* Remove the maximized state from the SYSCOMMAND test while we're not
2962 * interfering with a device. */
2963 ShowWindow(focus_window, SW_SHOWNORMAL);
2964 filter_messages = focus_window;
2966 device_desc.device_window = focus_window;
2967 if (!(device = create_device(focus_window, &device_desc)))
2969 skip("Failed to create a D3D device, skipping tests.\n");
2970 goto done;
2972 filter_messages = NULL;
2973 SetForegroundWindow(focus_window); /* For KDE. */
2974 flush_events();
2976 expect_messages = focus_loss_messages_filtered;
2977 windowposchanged_received = 0;
2978 SetForegroundWindow(GetDesktopWindow());
2979 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2980 expect_messages->message, expect_messages->window, i);
2981 ok(!windowposchanged_received, "Received WM_WINDOWPOSCHANGED but did not expect it, i=%u.\n", i);
2982 expect_messages = NULL;
2984 /* The window is iconic even though no message was sent. */
2985 ok(!IsIconic(focus_window) == !tests[i].iconic,
2986 "Expected IsIconic %u, got %u, i=%u.\n", tests[i].iconic, IsIconic(focus_window), i);
2988 ShowWindow(focus_window, SW_SHOWNOACTIVATE);
2989 ShowWindow(focus_window, SW_SHOWMINNOACTIVE);
2990 flush_events();
2992 syscommand_received = 0;
2993 expect_messages = sc_restore_messages;
2994 SendMessageA(focus_window, WM_SYSCOMMAND, SC_RESTORE, 0);
2995 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
2996 expect_messages->message, expect_messages->window, i);
2997 ok(syscommand_received == 1, "Got unexpected number of WM_SYSCOMMAND messages: %d.\n", syscommand_received);
2998 expect_messages = NULL;
2999 flush_events();
3001 /* For FVWM. */
3002 ShowWindow(focus_window, SW_RESTORE);
3003 flush_events();
3005 expect_messages = sc_minimize_messages;
3006 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MINIMIZE, 0);
3007 ok(!expect_messages->message, "Expected message %#x for window %#x, but didn't receive it, i=%u.\n",
3008 expect_messages->message, expect_messages->window, i);
3009 expect_messages = NULL;
3010 flush_events();
3012 expect_messages = sc_maximize_messages;
3013 SendMessageA(focus_window, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
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 expect_messages = NULL;
3017 flush_events();
3019 /* This test can't activate, drop focus and restore focus like in plain d3d9 because d3d9ex
3020 * immediately restores the device on activation. There are plenty of WM_WINDOWPOSCHANGED
3021 * messages that are generated by ShowWindow, so testing for their absence is pointless. */
3022 ShowWindow(focus_window, SW_MINIMIZE);
3023 ShowWindow(focus_window, SW_RESTORE);
3024 SetForegroundWindow(focus_window);
3025 flush_events();
3027 filter_messages = focus_window;
3028 ref = IDirect3DDevice9Ex_Release(device);
3029 ok(ref == 0, "The device was not properly freed: refcount %u, i=%u.\n", ref, i);
3031 device_desc.device_window = device_window;
3032 if (!(device = create_device(focus_window, &device_desc)))
3034 skip("Failed to create a D3D device, skipping tests.\n");
3035 goto done;
3038 proc = SetWindowLongPtrA(focus_window, GWLP_WNDPROC, (LONG_PTR)DefWindowProcA);
3039 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n",
3040 (LONG_PTR)test_proc);
3042 ref = IDirect3DDevice9Ex_Release(device);
3043 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3045 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3046 ok(proc == (LONG_PTR)DefWindowProcA, "Expected wndproc %#lx, got %#lx.\n",
3047 (LONG_PTR)DefWindowProcA, proc);
3049 done:
3050 filter_messages = NULL;
3051 DestroyWindow(device_window);
3052 DestroyWindow(focus_window);
3053 SetEvent(thread_params.test_finished);
3054 WaitForSingleObject(thread, INFINITE);
3055 CloseHandle(thread);
3058 CloseHandle(thread_params.test_finished);
3059 CloseHandle(thread_params.window_created);
3061 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3064 static void test_wndproc_windowed(void)
3066 struct wndproc_thread_param thread_params;
3067 struct device_desc device_desc;
3068 IDirect3DDevice9Ex *device;
3069 WNDCLASSA wc = {0};
3070 HANDLE thread;
3071 LONG_PTR proc;
3072 HRESULT hr;
3073 ULONG ref;
3074 DWORD res, tid;
3075 HWND tmp;
3077 wc.lpfnWndProc = test_proc;
3078 wc.lpszClassName = "d3d9_test_wndproc_wc";
3079 ok(RegisterClassA(&wc), "Failed to register window class.\n");
3081 thread_params.window_created = CreateEventA(NULL, FALSE, FALSE, NULL);
3082 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3083 thread_params.test_finished = CreateEventA(NULL, FALSE, FALSE, NULL);
3084 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3086 focus_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3087 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3088 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3089 device_window = CreateWindowA("d3d9_test_wndproc_wc", "d3d9_test",
3090 WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, 0, 0, registry_mode.dmPelsWidth,
3091 registry_mode.dmPelsHeight, 0, 0, 0, 0);
3092 thread = CreateThread(NULL, 0, wndproc_thread, &thread_params, 0, &tid);
3093 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3095 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3096 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3098 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3099 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3100 (LONG_PTR)test_proc, proc);
3101 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3102 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3103 (LONG_PTR)test_proc, proc);
3105 trace("device_window %p, focus_window %p, dummy_window %p.\n",
3106 device_window, focus_window, thread_params.dummy_window);
3108 tmp = GetFocus();
3109 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3110 if (thread_params.running_in_foreground)
3112 tmp = GetForegroundWindow();
3113 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3114 thread_params.dummy_window, tmp);
3116 else
3117 skip("Not running in foreground, skip foreground window test\n");
3119 filter_messages = focus_window;
3121 device_desc.device_window = device_window;
3122 device_desc.width = registry_mode.dmPelsWidth;
3123 device_desc.height = registry_mode.dmPelsHeight;
3124 device_desc.flags = 0;
3125 if (!(device = create_device(focus_window, &device_desc)))
3127 skip("Failed to create a D3D device, skipping tests.\n");
3128 goto done;
3131 tmp = GetFocus();
3132 ok(tmp == device_window, "Expected focus %p, got %p.\n", device_window, tmp);
3133 tmp = GetForegroundWindow();
3134 ok(tmp == thread_params.dummy_window, "Expected foreground window %p, got %p.\n",
3135 thread_params.dummy_window, tmp);
3137 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3138 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3139 (LONG_PTR)test_proc, proc);
3141 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3142 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3143 (LONG_PTR)test_proc, proc);
3145 filter_messages = NULL;
3147 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3148 hr = reset_device(device, &device_desc);
3149 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3151 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3152 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3153 (LONG_PTR)test_proc, proc);
3155 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3156 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3158 device_desc.flags = 0;
3159 hr = reset_device(device, &device_desc);
3160 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3162 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3163 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3164 (LONG_PTR)test_proc, proc);
3166 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3167 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3168 (LONG_PTR)test_proc, proc);
3170 filter_messages = focus_window;
3172 ref = IDirect3DDevice9Ex_Release(device);
3173 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3175 filter_messages = device_window;
3177 device_desc.device_window = focus_window;
3178 if (!(device = create_device(focus_window, &device_desc)))
3180 skip("Failed to create a D3D device, skipping tests.\n");
3181 goto done;
3184 filter_messages = NULL;
3186 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3187 hr = reset_device(device, &device_desc);
3188 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3190 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3191 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3192 (LONG_PTR)test_proc, proc);
3194 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3195 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3197 device_desc.flags = 0;
3198 hr = reset_device(device, &device_desc);
3199 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3201 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3202 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3203 (LONG_PTR)test_proc, proc);
3205 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3206 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3207 (LONG_PTR)test_proc, proc);
3209 filter_messages = device_window;
3211 ref = IDirect3DDevice9Ex_Release(device);
3212 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3214 device_desc.device_window = device_window;
3215 if (!(device = create_device(focus_window, &device_desc)))
3217 skip("Failed to create a D3D device, skipping tests.\n");
3218 goto done;
3221 filter_messages = NULL;
3223 device_desc.flags = CREATE_DEVICE_FULLSCREEN;
3224 hr = reset_device(device, &device_desc);
3225 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3227 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3228 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3229 (LONG_PTR)test_proc, proc);
3231 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3232 ok(proc != (LONG_PTR)test_proc, "Expected wndproc != %#lx.\n", (LONG_PTR)test_proc);
3234 device_desc.flags = 0;
3235 hr = reset_device(device, &device_desc);
3236 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3238 proc = GetWindowLongPtrA(device_window, GWLP_WNDPROC);
3239 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3240 (LONG_PTR)test_proc, proc);
3242 proc = GetWindowLongPtrA(focus_window, GWLP_WNDPROC);
3243 ok(proc == (LONG_PTR)test_proc, "Expected wndproc %#lx, got %#lx.\n",
3244 (LONG_PTR)test_proc, proc);
3246 filter_messages = device_window;
3248 ref = IDirect3DDevice9Ex_Release(device);
3249 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3251 done:
3252 filter_messages = NULL;
3254 SetEvent(thread_params.test_finished);
3255 WaitForSingleObject(thread, INFINITE);
3256 CloseHandle(thread_params.test_finished);
3257 CloseHandle(thread_params.window_created);
3258 CloseHandle(thread);
3260 DestroyWindow(device_window);
3261 DestroyWindow(focus_window);
3262 UnregisterClassA("d3d9_test_wndproc_wc", GetModuleHandleA(NULL));
3265 static void test_window_style(void)
3267 RECT focus_rect, device_rect, fullscreen_rect, r, r2;
3268 LONG device_style, device_exstyle, expected_style;
3269 LONG focus_style, focus_exstyle;
3270 struct device_desc device_desc;
3271 LONG style;
3272 IDirect3DDevice9Ex *device;
3273 HRESULT hr;
3274 ULONG ref;
3275 BOOL ret;
3276 static const struct
3278 LONG style_flags;
3279 DWORD device_flags;
3280 LONG focus_loss_style;
3281 LONG create2_style, create2_exstyle;
3283 tests[] =
3285 {0, 0, 0, WS_VISIBLE, WS_EX_TOPMOST},
3286 {WS_VISIBLE, 0, WS_MINIMIZE, WS_VISIBLE, WS_EX_TOPMOST},
3287 {0, CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
3288 {WS_VISIBLE, CREATE_DEVICE_NOWINDOWCHANGES, 0, 0, 0},
3290 unsigned int i;
3292 SetRect(&fullscreen_rect, 0, 0, registry_mode.dmPelsWidth, registry_mode.dmPelsHeight);
3294 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3296 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3297 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3298 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3299 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3301 device_style = GetWindowLongA(device_window, GWL_STYLE);
3302 device_exstyle = GetWindowLongA(device_window, GWL_EXSTYLE);
3303 focus_style = GetWindowLongA(focus_window, GWL_STYLE);
3304 focus_exstyle = GetWindowLongA(focus_window, GWL_EXSTYLE);
3306 GetWindowRect(focus_window, &focus_rect);
3307 GetWindowRect(device_window, &device_rect);
3309 device_desc.device_window = device_window;
3310 device_desc.width = registry_mode.dmPelsWidth;
3311 device_desc.height = registry_mode.dmPelsHeight;
3312 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
3313 if (!(device = create_device(focus_window, &device_desc)))
3315 skip("Failed to create a D3D device, skipping tests.\n");
3316 DestroyWindow(device_window);
3317 DestroyWindow(focus_window);
3318 return;
3321 style = GetWindowLongA(device_window, GWL_STYLE);
3322 todo_wine ok(style == device_style, "Expected device window style %#x, got %#x, i=%u.\n",
3323 device_style, style, i);
3324 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3325 todo_wine ok(style == device_exstyle, "Expected device window extended style %#x, got %#x, i=%u.\n",
3326 device_exstyle, style, i);
3328 style = GetWindowLongA(focus_window, GWL_STYLE);
3329 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
3330 focus_style, style, i);
3331 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3332 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
3333 focus_exstyle, style, i);
3335 GetWindowRect(device_window, &r);
3336 if (tests[i].device_flags & CREATE_DEVICE_NOWINDOWCHANGES)
3337 todo_wine ok(EqualRect(&r, &device_rect), "Expected %s, got %s, i=%u.\n",
3338 wine_dbgstr_rect(&device_rect), wine_dbgstr_rect(&r), i);
3339 else
3340 ok(EqualRect(&r, &fullscreen_rect), "Expected %s, got %s, i=%u.\n",
3341 wine_dbgstr_rect(&fullscreen_rect), wine_dbgstr_rect(&r), i);
3342 GetClientRect(device_window, &r2);
3343 todo_wine ok(!EqualRect(&r, &r2), "Client rect and window rect are equal, i=%u.\n", i);
3344 GetWindowRect(focus_window, &r);
3345 ok(EqualRect(&r, &focus_rect), "Expected %s, got %s, i=%u.\n",
3346 wine_dbgstr_rect(&focus_rect), wine_dbgstr_rect(&r), i);
3348 device_desc.flags = 0;
3349 hr = reset_device(device, &device_desc);
3350 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x.\n", hr);
3352 style = GetWindowLongA(device_window, GWL_STYLE);
3353 todo_wine_if (!(tests[i].style_flags & WS_VISIBLE))
3354 ok(style == device_style, "Expected device window style %#x, got %#x, i=%u.\n",
3355 device_style, style, i);
3356 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3357 todo_wine ok(style == device_exstyle, "Expected device window extended style %#x, got %#x, i=%u.\n",
3358 device_exstyle, style, i);
3360 style = GetWindowLongA(focus_window, GWL_STYLE);
3361 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
3362 focus_style, style, i);
3363 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3364 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
3365 focus_exstyle, style, i);
3367 ref = IDirect3DDevice9Ex_Release(device);
3368 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3370 style = GetWindowLongA(device_window, GWL_STYLE);
3371 todo_wine_if (!(device_style & WS_VISIBLE))
3372 ok(style == device_style, "Expected device window style %#x, got %#x, i=%u.\n",
3373 device_style, style, i);
3374 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3375 todo_wine ok(style == device_exstyle, "Expected device window extended style %#x, got %#x, i=%u.\n",
3376 device_exstyle, style, i);
3378 style = GetWindowLongA(focus_window, GWL_STYLE);
3379 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
3380 focus_style, style, i);
3381 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3382 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
3383 focus_exstyle, style, i);
3385 /* The second time a device is created on the window the window becomes visible and
3386 * topmost if D3DCREATE_NOWINDOWCHANGES is not set. */
3387 device_desc.flags = CREATE_DEVICE_FULLSCREEN | tests[i].device_flags;
3388 device = create_device(focus_window, &device_desc);
3389 ok(!!device, "Failed to create a D3D device.\n");
3390 style = GetWindowLongA(device_window, GWL_STYLE);
3391 expected_style = device_style | tests[i].create2_style;
3392 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
3393 expected_style, style, i);
3394 expected_style = device_exstyle | tests[i].create2_exstyle;
3395 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3396 todo_wine ok(style == expected_style, "Expected device window extended style %#x, got %#x, i=%u.\n",
3397 expected_style, style, i);
3399 style = GetWindowLongA(focus_window, GWL_STYLE);
3400 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
3401 focus_style, style, i);
3402 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3403 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
3404 focus_exstyle, style, i);
3405 ref = IDirect3DDevice9Ex_Release(device);
3406 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3408 DestroyWindow(device_window);
3409 DestroyWindow(focus_window);
3410 focus_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3411 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3412 device_window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_OVERLAPPEDWINDOW | tests[i].style_flags,
3413 0, 0, registry_mode.dmPelsWidth / 2, registry_mode.dmPelsHeight / 2, 0, 0, 0, 0);
3415 device_desc.device_window = device_window;
3416 device = create_device(focus_window, &device_desc);
3417 ok(!!device, "Failed to create a D3D device.\n");
3418 ret = SetForegroundWindow(GetDesktopWindow());
3419 ok(ret, "Failed to set foreground window.\n");
3421 style = GetWindowLongA(device_window, GWL_STYLE);
3422 expected_style = device_style | tests[i].focus_loss_style;
3423 todo_wine ok(style == expected_style, "Expected device window style %#x, got %#x, i=%u.\n",
3424 expected_style, style, i);
3425 style = GetWindowLongA(device_window, GWL_EXSTYLE);
3426 todo_wine ok(style == device_exstyle, "Expected device window extended style %#x, got %#x, i=%u.\n",
3427 device_exstyle, style, i);
3429 style = GetWindowLongA(focus_window, GWL_STYLE);
3430 ok(style == focus_style, "Expected focus window style %#x, got %#x, i=%u.\n",
3431 focus_style, style, i);
3432 style = GetWindowLongA(focus_window, GWL_EXSTYLE);
3433 ok(style == focus_exstyle, "Expected focus window extended style %#x, got %#x, i=%u.\n",
3434 focus_exstyle, style, i);
3436 ref = IDirect3DDevice9Ex_Release(device);
3437 ok(ref == 0, "The device was not properly freed: refcount %u.\n", ref);
3439 DestroyWindow(device_window);
3440 DestroyWindow(focus_window);
3444 static void test_swapchain_parameters(void)
3446 IDirect3DDevice9Ex *device;
3447 IDirect3D9Ex *d3d9ex;
3448 HWND window;
3449 HRESULT hr;
3450 unsigned int i;
3451 D3DPRESENT_PARAMETERS present_parameters, present_parameters_windowed = {0}, present_parameters2;
3452 IDirect3DSwapChain9 *swapchain;
3453 D3DDISPLAYMODEEX mode = {0};
3454 static const struct
3456 BOOL windowed;
3457 UINT backbuffer_count;
3458 D3DSWAPEFFECT swap_effect;
3459 HRESULT hr;
3461 tests[] =
3463 /* Swap effect 0 is not allowed. */
3464 {TRUE, 1, 0, D3DERR_INVALIDCALL},
3465 {FALSE, 1, 0, D3DERR_INVALIDCALL},
3467 /* All (non-ex) swap effects are allowed in
3468 * windowed and fullscreen mode. */
3469 {TRUE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
3470 {TRUE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
3471 {FALSE, 1, D3DSWAPEFFECT_DISCARD, D3D_OK},
3472 {FALSE, 1, D3DSWAPEFFECT_FLIP, D3D_OK},
3473 {FALSE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
3475 /* Only one backbuffer in copy mode. */
3476 {TRUE, 0, D3DSWAPEFFECT_COPY, D3D_OK},
3477 {TRUE, 1, D3DSWAPEFFECT_COPY, D3D_OK},
3478 {TRUE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
3479 {FALSE, 2, D3DSWAPEFFECT_COPY, D3DERR_INVALIDCALL},
3481 /* Ok with the others, in fullscreen and windowed mode. */
3482 {TRUE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
3483 {TRUE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
3484 {FALSE, 2, D3DSWAPEFFECT_DISCARD, D3D_OK},
3485 {FALSE, 2, D3DSWAPEFFECT_FLIP, D3D_OK},
3487 /* D3D9Ex swap effects. Flipex works, Overlay is complicated
3488 * and depends on HW features, pixel format, etc. */
3489 {TRUE, 1, D3DSWAPEFFECT_FLIPEX, D3D_OK},
3490 {TRUE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
3491 {FALSE, 1, D3DSWAPEFFECT_FLIPEX, D3D_OK},
3492 {FALSE, 1, D3DSWAPEFFECT_FLIPEX + 1, D3DERR_INVALIDCALL},
3494 /* 30 is the highest allowed backbuffer count. */
3495 {TRUE, 30, D3DSWAPEFFECT_DISCARD, D3D_OK},
3496 {TRUE, 31, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
3497 {TRUE, 30, D3DSWAPEFFECT_FLIP, D3D_OK},
3498 {TRUE, 31, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
3499 {FALSE, 30, D3DSWAPEFFECT_DISCARD, D3D_OK},
3500 {FALSE, 31, D3DSWAPEFFECT_DISCARD, D3DERR_INVALIDCALL},
3501 {FALSE, 30, D3DSWAPEFFECT_FLIP, D3D_OK},
3502 {FALSE, 31, D3DSWAPEFFECT_FLIP, D3DERR_INVALIDCALL},
3505 window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW,
3506 0, 0, 640, 480, NULL, NULL, NULL, NULL);
3507 hr = pDirect3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex);
3508 if (FAILED(hr))
3510 skip("Direct3D9Ex is not available (%#x)\n", hr);
3511 return;
3514 if (!(device = create_device(window, NULL)))
3516 skip("Failed to create a D3D device, skipping tests.\n");
3517 IDirect3D9Ex_Release(d3d9ex);
3518 DestroyWindow(window);
3519 return;
3521 IDirect3DDevice9Ex_Release(device);
3523 present_parameters_windowed.BackBufferWidth = registry_mode.dmPelsWidth;
3524 present_parameters_windowed.BackBufferHeight = registry_mode.dmPelsHeight;
3525 present_parameters_windowed.hDeviceWindow = window;
3526 present_parameters_windowed.BackBufferFormat = D3DFMT_X8R8G8B8;
3527 present_parameters_windowed.SwapEffect = D3DSWAPEFFECT_COPY;
3528 present_parameters_windowed.Windowed = TRUE;
3529 present_parameters_windowed.BackBufferCount = 1;
3531 mode.Size = sizeof(mode);
3532 mode.Width = registry_mode.dmPelsWidth;
3533 mode.Height = registry_mode.dmPelsHeight;
3534 mode.RefreshRate = 0;
3535 mode.Format = D3DFMT_X8R8G8B8;
3536 mode.ScanLineOrdering = 0;
3538 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
3540 memset(&present_parameters, 0, sizeof(present_parameters));
3541 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
3542 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
3543 present_parameters.hDeviceWindow = window;
3544 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
3546 present_parameters.SwapEffect = tests[i].swap_effect;
3547 present_parameters.Windowed = tests[i].windowed;
3548 present_parameters.BackBufferCount = tests[i].backbuffer_count;
3550 hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3551 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters,
3552 tests[i].windowed ? NULL : &mode, &device);
3553 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
3554 if (SUCCEEDED(hr))
3556 UINT bb_count = tests[i].backbuffer_count ? tests[i].backbuffer_count : 1;
3558 hr = IDirect3DDevice9Ex_GetSwapChain(device, 0, &swapchain);
3559 ok(SUCCEEDED(hr), "Failed to get swapchain, hr %#x, test %u.\n", hr, i);
3561 hr = IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters2);
3562 ok(SUCCEEDED(hr), "Failed to get present parameters, hr %#x, test %u.\n", hr, i);
3563 ok(present_parameters2.SwapEffect == tests[i].swap_effect, "Swap effect changed from %u to %u, test %u.\n",
3564 tests[i].swap_effect, present_parameters2.SwapEffect, i);
3565 ok(present_parameters2.BackBufferCount == bb_count, "Backbuffer count changed from %u to %u, test %u.\n",
3566 bb_count, present_parameters2.BackBufferCount, i);
3567 ok(present_parameters2.Windowed == tests[i].windowed, "Windowed changed from %u to %u, test %u.\n",
3568 tests[i].windowed, present_parameters2.Windowed, i);
3570 IDirect3DSwapChain9_Release(swapchain);
3571 IDirect3DDevice9Ex_Release(device);
3574 hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
3575 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters_windowed, NULL, &device);
3576 ok(SUCCEEDED(hr), "Failed to create device, hr %#x, test %u.\n", hr, i);
3578 memset(&present_parameters, 0, sizeof(present_parameters));
3579 present_parameters.BackBufferWidth = registry_mode.dmPelsWidth;
3580 present_parameters.BackBufferHeight = registry_mode.dmPelsHeight;
3581 present_parameters.hDeviceWindow = window;
3582 present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
3584 present_parameters.SwapEffect = tests[i].swap_effect;
3585 present_parameters.Windowed = tests[i].windowed;
3586 present_parameters.BackBufferCount = tests[i].backbuffer_count;
3588 hr = IDirect3DDevice9Ex_ResetEx(device, &present_parameters, tests[i].windowed ? NULL : &mode);
3589 ok(hr == tests[i].hr, "Expected hr %x, got %x, test %u.\n", tests[i].hr, hr, i);
3591 if (FAILED(hr))
3593 hr = IDirect3DDevice9Ex_ResetEx(device, &present_parameters_windowed, NULL);
3594 ok(SUCCEEDED(hr), "Failed to reset device, hr %#x, test %u.\n", hr, i);
3596 IDirect3DDevice9Ex_Release(device);
3599 IDirect3D9Ex_Release(d3d9ex);
3600 DestroyWindow(window);
3603 static void test_backbuffer_resize(void)
3605 D3DPRESENT_PARAMETERS present_parameters = {0};
3606 IDirect3DSurface9 *backbuffer, *old_backbuffer;
3607 D3DSURFACE_DESC surface_desc;
3608 IDirect3DDevice9Ex *device;
3609 D3DCOLOR color;
3610 ULONG refcount;
3611 HWND window;
3612 HRESULT hr;
3614 static const struct
3616 float position[3];
3617 DWORD diffuse;
3619 quad[] =
3621 {{-1.0f, -1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3622 {{-1.0f, 1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3623 {{ 1.0f, -1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3624 {{ 1.0f, 1.0f, 0.1f}, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00)},
3627 window = create_window();
3628 if (!(device = create_device(window, NULL)))
3630 skip("Failed to create a D3D device.\n");
3631 DestroyWindow(window);
3632 return;
3635 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
3636 ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
3637 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3638 ok(SUCCEEDED(hr), "Failed to disable Z test, hr %#x.\n", hr);
3639 hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3640 ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
3641 hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
3642 ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
3644 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3645 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3646 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
3647 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3649 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
3650 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
3651 color = get_pixel_color(device, 1, 1);
3652 ok(color == 0x00ff0000, "Got unexpected color 0x%08x.\n", color);
3654 present_parameters.BackBufferWidth = 800;
3655 present_parameters.BackBufferHeight = 600;
3656 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
3657 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
3658 present_parameters.hDeviceWindow = NULL;
3659 present_parameters.Windowed = TRUE;
3660 present_parameters.EnableAutoDepthStencil = TRUE;
3661 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
3662 hr = IDirect3DDevice9_Reset(device, &present_parameters);
3663 ok(SUCCEEDED(hr), "Failed to reset, hr %#x.\n", hr);
3665 old_backbuffer = backbuffer;
3666 hr = IDirect3DSurface9_GetDesc(old_backbuffer, &surface_desc);
3667 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3668 todo_wine ok(surface_desc.Width == 640, "Got unexpected width %u.\n", surface_desc.Width);
3669 todo_wine ok(surface_desc.Height == 480, "Got unexpected height %u.\n", surface_desc.Height);
3670 refcount = IDirect3DSurface9_Release(old_backbuffer);
3671 ok(!refcount, "Surface has %u references left.\n", refcount);
3673 hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
3674 ok(SUCCEEDED(hr), "Failed to get backbuffer, hr %#x.\n", hr);
3675 todo_wine ok(backbuffer != old_backbuffer, "Expected new backbuffer surface.\n");
3677 hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
3678 ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3680 hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 1.0f, 0);
3681 ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
3682 color = get_pixel_color(device, 1, 1);
3683 ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
3684 color = get_pixel_color(device, 700, 500);
3685 ok(color == 0x00ffff00, "Got unexpected color 0x%08x.\n", color);
3687 hr = IDirect3DDevice9_BeginScene(device);
3688 ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3689 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
3690 ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3691 hr = IDirect3DDevice9_EndScene(device);
3692 ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3693 color = get_pixel_color(device, 1, 1);
3694 ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
3695 color = get_pixel_color(device, 700, 500);
3696 ok(color == 0x0000ff00, "Got unexpected color 0x%08x.\n", color);
3698 IDirect3DSurface9_Release(backbuffer);
3699 refcount = IDirect3DDevice9_Release(device);
3700 ok(!refcount, "Device has %u references left.\n", refcount);
3701 DestroyWindow(window);
3704 static void test_format_unknown(void)
3706 IDirect3DDevice9Ex *device;
3707 UINT refcount;
3708 HWND window;
3709 void *iface;
3710 HRESULT hr;
3712 window = create_window();
3713 if (!(device = create_device(window, NULL)))
3715 skip("Failed to create a D3D device.\n");
3716 DestroyWindow(window);
3717 return;
3720 iface = (void *)0xdeadbeef;
3721 hr = IDirect3DDevice9Ex_CreateRenderTarget(device, 64, 64,
3722 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL);
3723 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3724 ok(!iface, "Got unexpected iface %p.\n", iface);
3726 iface = (void *)0xdeadbeef;
3727 hr = IDirect3DDevice9Ex_CreateRenderTargetEx(device, 64, 64,
3728 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, FALSE, (IDirect3DSurface9 **)&iface, NULL, 0);
3729 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3730 ok(!iface, "Got unexpected iface %p.\n", iface);
3732 iface = (void *)0xdeadbeef;
3733 hr = IDirect3DDevice9Ex_CreateDepthStencilSurface(device, 64, 64,
3734 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL);
3735 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3736 ok(!iface, "Got unexpected iface %p.\n", iface);
3738 iface = (void *)0xdeadbeef;
3739 hr = IDirect3DDevice9Ex_CreateDepthStencilSurfaceEx(device, 64, 64,
3740 D3DFMT_UNKNOWN, D3DMULTISAMPLE_NONE, 0, TRUE, (IDirect3DSurface9 **)&iface, NULL, 0);
3741 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3742 ok(!iface, "Got unexpected iface %p.\n", iface);
3744 iface = (void *)0xdeadbeef;
3745 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurface(device, 64, 64,
3746 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL);
3747 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3748 ok(!iface, "Got unexpected iface %p.\n", iface);
3750 iface = (void *)0xdeadbeef;
3751 hr = IDirect3DDevice9Ex_CreateOffscreenPlainSurfaceEx(device, 64, 64,
3752 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DSurface9 **)&iface, NULL, 9);
3753 todo_wine ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3754 todo_wine ok(!iface, "Got unexpected iface %p.\n", iface);
3756 iface = (void *)0xdeadbeef;
3757 hr = IDirect3DDevice9Ex_CreateTexture(device, 64, 64, 1, 0,
3758 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DTexture9 **)&iface, NULL);
3759 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3760 ok(!iface, "Got unexpected iface %p.\n", iface);
3762 iface = (void *)0xdeadbeef;
3763 hr = IDirect3DDevice9Ex_CreateCubeTexture(device, 64, 1, 0,
3764 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DCubeTexture9 **)&iface, NULL);
3765 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3766 ok(!iface, "Got unexpected iface %p.\n", iface);
3768 iface = (void *)0xdeadbeef;
3769 hr = IDirect3DDevice9Ex_CreateVolumeTexture(device, 64, 64, 1, 1, 0,
3770 D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, (IDirect3DVolumeTexture9 **)&iface, NULL);
3771 ok(hr == D3DERR_INVALIDCALL, "Got unexpected hr %#x.\n", hr);
3772 ok(!iface, "Got unexpected iface %p.\n", iface);
3774 refcount = IDirect3DDevice9Ex_Release(device);
3775 ok(!refcount, "Device has %u references left.\n", refcount);
3776 DestroyWindow(window);
3779 START_TEST(d3d9ex)
3781 DEVMODEW current_mode;
3783 d3d9_handle = LoadLibraryA("d3d9.dll");
3784 if (!d3d9_handle)
3786 skip("Could not load d3d9.dll\n");
3787 return;
3790 pDirect3DCreate9Ex = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9Ex");
3791 if (!pDirect3DCreate9Ex) {
3792 win_skip("Failed to get address of Direct3DCreate9Ex\n");
3793 return;
3796 memset(&current_mode, 0, sizeof(current_mode));
3797 current_mode.dmSize = sizeof(current_mode);
3798 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &current_mode), "Failed to get display mode.\n");
3799 registry_mode.dmSize = sizeof(registry_mode);
3800 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
3801 if (current_mode.dmPelsWidth != registry_mode.dmPelsWidth
3802 || current_mode.dmPelsHeight != registry_mode.dmPelsHeight)
3804 skip("Current mode does not match registry mode, skipping test.\n");
3805 return;
3808 test_qi_base_to_ex();
3809 test_qi_ex_to_base();
3810 test_swapchain_get_displaymode_ex();
3811 test_get_adapter_luid();
3812 test_get_adapter_displaymode_ex();
3813 test_create_depth_stencil_surface_ex();
3814 test_user_memory();
3815 test_reset();
3816 test_reset_ex();
3817 test_reset_resources();
3818 test_vidmem_accounting();
3819 test_user_memory_getdc();
3820 test_lost_device();
3821 test_unsupported_shaders();
3822 test_wndproc();
3823 test_wndproc_windowed();
3824 test_window_style();
3825 test_swapchain_parameters();
3826 test_backbuffer_resize();
3827 test_format_unknown();