dxgi/tests: Some spelling fixes in ok() messages.
[wine.git] / dlls / dxgi / tests / device.c
blobdb4c57e80973186fcdd1caeb32fc032feb382623
1 /*
2 * Copyright 2008 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <assert.h>
20 #define COBJMACROS
21 #include "initguid.h"
22 #include "d3d11.h"
23 #include "wine/test.h"
25 enum frame_latency
27 DEFAULT_FRAME_LATENCY = 3,
28 MAX_FRAME_LATENCY = 16,
31 static DEVMODEW registry_mode;
33 static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
35 static ULONG get_refcount(IUnknown *iface)
37 IUnknown_AddRef(iface);
38 return IUnknown_Release(iface);
41 #define MODE_DESC_IGNORE_RESOLUTION 0x00000001u
42 #define MODE_DESC_IGNORE_REFRESH_RATE 0x00000002u
43 #define MODE_DESC_IGNORE_FORMAT 0x00000004u
44 #define MODE_DESC_IGNORE_SCANLINE_ORDERING 0x00000008u
45 #define MODE_DESC_IGNORE_SCALING 0x00000010u
47 #define MODE_DESC_CHECK_RESOLUTION (~MODE_DESC_IGNORE_RESOLUTION)
48 #define MODE_DESC_CHECK_FORMAT (~MODE_DESC_IGNORE_FORMAT)
50 #define check_mode_desc(a, b, c) check_mode_desc_(__LINE__, a, b, c)
51 static void check_mode_desc_(unsigned int line, const DXGI_MODE_DESC *desc,
52 const DXGI_MODE_DESC *expected_desc, unsigned int ignore_flags)
54 if (!(ignore_flags & MODE_DESC_IGNORE_RESOLUTION))
56 ok_(__FILE__, line)(desc->Width == expected_desc->Width
57 && desc->Height == expected_desc->Height,
58 "Got resolution %ux%u, expected %ux%u.\n",
59 desc->Width, desc->Height, expected_desc->Width, expected_desc->Height);
61 if (!(ignore_flags & MODE_DESC_IGNORE_REFRESH_RATE))
63 ok_(__FILE__, line)(desc->RefreshRate.Numerator == expected_desc->RefreshRate.Numerator
64 && desc->RefreshRate.Denominator == expected_desc->RefreshRate.Denominator,
65 "Got refresh rate %u / %u, expected %u / %u.\n",
66 desc->RefreshRate.Numerator, desc->RefreshRate.Denominator,
67 expected_desc->RefreshRate.Denominator, expected_desc->RefreshRate.Denominator);
69 if (!(ignore_flags & MODE_DESC_IGNORE_FORMAT))
71 ok_(__FILE__, line)(desc->Format == expected_desc->Format,
72 "Got format %#x, expected %#x.\n", desc->Format, expected_desc->Format);
74 if (!(ignore_flags & MODE_DESC_IGNORE_SCANLINE_ORDERING))
76 ok_(__FILE__, line)(desc->ScanlineOrdering == expected_desc->ScanlineOrdering,
77 "Got scanline ordering %#x, expected %#x.\n",
78 desc->ScanlineOrdering, expected_desc->ScanlineOrdering);
80 if (!(ignore_flags & MODE_DESC_IGNORE_SCALING))
82 ok_(__FILE__, line)(desc->Scaling == expected_desc->Scaling,
83 "Got scaling %#x, expected %#x.\n",
84 desc->Scaling, expected_desc->Scaling);
88 #define check_output_desc(a, b) check_output_desc_(__LINE__, a, b)
89 static void check_output_desc_(unsigned int line, const DXGI_OUTPUT_DESC *desc,
90 const struct DXGI_OUTPUT_DESC *expected_desc)
92 ok_(__FILE__, line)(!lstrcmpW(desc->DeviceName, expected_desc->DeviceName),
93 "Got unexpected device name %s, expected %s.\n",
94 wine_dbgstr_w(desc->DeviceName), wine_dbgstr_w(expected_desc->DeviceName));
95 ok_(__FILE__, line)(EqualRect(&desc->DesktopCoordinates, &expected_desc->DesktopCoordinates),
96 "Got unexpected desktop coordinates %s, expected %s.\n",
97 wine_dbgstr_rect(&desc->DesktopCoordinates),
98 wine_dbgstr_rect(&expected_desc->DesktopCoordinates));
101 #define check_output_equal(a, b) check_output_equal_(__LINE__, a, b)
102 static void check_output_equal_(unsigned int line, IDXGIOutput *output1, IDXGIOutput *output2)
104 DXGI_OUTPUT_DESC desc1, desc2;
105 HRESULT hr;
107 hr = IDXGIOutput_GetDesc(output1, &desc1);
108 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
109 hr = IDXGIOutput_GetDesc(output2, &desc2);
110 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
111 check_output_desc_(line, &desc1, &desc2);
114 static BOOL output_belongs_to_adapter(IDXGIOutput *output, IDXGIAdapter *adapter)
116 DXGI_OUTPUT_DESC output_desc, desc;
117 unsigned int output_idx;
118 IDXGIOutput *o;
119 HRESULT hr;
121 hr = IDXGIOutput_GetDesc(output, &output_desc);
122 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
124 for (output_idx = 0; IDXGIAdapter_EnumOutputs(adapter, output_idx, &o) != DXGI_ERROR_NOT_FOUND; ++output_idx)
126 hr = IDXGIOutput_GetDesc(o, &desc);
127 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
128 IDXGIOutput_Release(o);
130 if (!lstrcmpW(desc.DeviceName, output_desc.DeviceName)
131 && EqualRect(&desc.DesktopCoordinates, &output_desc.DesktopCoordinates))
132 return TRUE;
135 return FALSE;
138 struct fullscreen_state
140 RECT window_rect;
141 RECT client_rect;
142 HMONITOR monitor;
143 RECT monitor_rect;
146 struct swapchain_fullscreen_state
148 struct fullscreen_state fullscreen_state;
149 BOOL fullscreen;
150 IDXGIOutput *target;
153 #define capture_fullscreen_state(a, b) capture_fullscreen_state_(__LINE__, a, b)
154 static void capture_fullscreen_state_(unsigned int line, struct fullscreen_state *state, HWND window)
156 MONITORINFOEXW monitor_info;
157 BOOL ret;
159 ret = GetWindowRect(window, &state->window_rect);
160 ok_(__FILE__, line)(ret, "GetWindowRect failed.\n");
161 ret = GetClientRect(window, &state->client_rect);
162 ok_(__FILE__, line)(ret, "GetClientRect failed.\n");
164 state->monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
165 ok_(__FILE__, line)(!!state->monitor, "Failed to get monitor from window.\n");
167 monitor_info.cbSize = sizeof(monitor_info);
168 ret = GetMonitorInfoW(state->monitor, (MONITORINFO *)&monitor_info);
169 ok_(__FILE__, line)(ret, "Failed to get monitor info.\n");
170 state->monitor_rect = monitor_info.rcMonitor;
173 #define check_fullscreen_state(a, b) check_fullscreen_state_(__LINE__, a, b)
174 static void check_fullscreen_state_(unsigned int line, const struct fullscreen_state *state,
175 const struct fullscreen_state *expected_state)
177 ok_(__FILE__, line)(EqualRect(&state->window_rect, &expected_state->window_rect),
178 "Got window rect %s, expected %s.\n",
179 wine_dbgstr_rect(&state->window_rect), wine_dbgstr_rect(&expected_state->window_rect));
180 ok_(__FILE__, line)(EqualRect(&state->client_rect, &expected_state->client_rect),
181 "Got client rect %s, expected %s.\n",
182 wine_dbgstr_rect(&state->client_rect), wine_dbgstr_rect(&expected_state->client_rect));
183 ok_(__FILE__, line)(state->monitor == expected_state->monitor,
184 "Got monitor %p, expected %p.\n",
185 state->monitor, expected_state->monitor);
186 ok_(__FILE__, line)(EqualRect(&state->monitor_rect, &expected_state->monitor_rect),
187 "Got monitor rect %s, expected %s.\n",
188 wine_dbgstr_rect(&state->monitor_rect), wine_dbgstr_rect(&expected_state->monitor_rect));
191 #define check_window_fullscreen_state(a, b) check_window_fullscreen_state_(__LINE__, a, b)
192 static void check_window_fullscreen_state_(unsigned int line, HWND window,
193 const struct fullscreen_state *expected_state)
195 struct fullscreen_state current_state;
196 capture_fullscreen_state_(line, &current_state, window);
197 check_fullscreen_state_(line, &current_state, expected_state);
200 #define check_swapchain_fullscreen_state(a, b) check_swapchain_fullscreen_state_(__LINE__, a, b)
201 static void check_swapchain_fullscreen_state_(unsigned int line, IDXGISwapChain *swapchain,
202 const struct swapchain_fullscreen_state *expected_state)
204 IDXGIOutput *containing_output, *target;
205 DXGI_SWAP_CHAIN_DESC swapchain_desc;
206 BOOL fullscreen;
207 HRESULT hr;
209 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
210 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
211 check_window_fullscreen_state_(line, swapchain_desc.OutputWindow, &expected_state->fullscreen_state);
213 ok_(__FILE__, line)(swapchain_desc.Windowed == !expected_state->fullscreen,
214 "Got windowed %#x, expected %#x.\n",
215 swapchain_desc.Windowed, !expected_state->fullscreen);
217 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
218 ok_(__FILE__, line)(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
219 ok_(__FILE__, line)(fullscreen == expected_state->fullscreen, "Got fullscreen %#x, expected %#x.\n",
220 fullscreen, expected_state->fullscreen);
222 if (!swapchain_desc.Windowed && expected_state->fullscreen)
224 IDXGIAdapter *adapter;
225 IDXGIDevice *device;
227 hr = IDXGISwapChain_GetDevice(swapchain, &IID_IDXGIDevice, (void **)&device);
228 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDevice failed, hr %#x.\n", hr);
229 hr = IDXGIDevice_GetAdapter(device, &adapter);
230 ok_(__FILE__, line)(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
231 IDXGIDevice_Release(device);
233 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
234 ok_(__FILE__, line)(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
236 check_output_equal_(line, target, expected_state->target);
237 ok_(__FILE__, line)(target == containing_output, "Got target %p, expected %p.\n",
238 target, containing_output);
239 ok_(__FILE__, line)(output_belongs_to_adapter(target, adapter),
240 "Output %p doesn't belong to adapter %p.\n",
241 target, adapter);
243 IDXGIOutput_Release(target);
244 IDXGIOutput_Release(containing_output);
245 IDXGIAdapter_Release(adapter);
247 else
249 ok_(__FILE__, line)(!target, "Got unexpected target %p.\n", target);
253 #define compute_expected_swapchain_fullscreen_state_after_fullscreen_change(a, b, c, d, e, f) \
254 compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(__LINE__, a, b, c, d, e, f)
255 static void compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(unsigned int line,
256 struct swapchain_fullscreen_state *state, const DXGI_SWAP_CHAIN_DESC *swapchain_desc,
257 const RECT *old_monitor_rect, unsigned int new_width, unsigned int new_height, IDXGIOutput *target)
259 if (!new_width && !new_height)
261 RECT client_rect;
262 GetClientRect(swapchain_desc->OutputWindow, &client_rect);
263 new_width = client_rect.right - client_rect.left;
264 new_height = client_rect.bottom - client_rect.top;
267 if (target)
269 DXGI_MODE_DESC mode_desc = swapchain_desc->BufferDesc;
270 HRESULT hr;
272 mode_desc.Width = new_width;
273 mode_desc.Height = new_height;
274 hr = IDXGIOutput_FindClosestMatchingMode(target, &mode_desc, &mode_desc, NULL);
275 ok_(__FILE__, line)(SUCCEEDED(hr), "FindClosestMatchingMode failed, hr %#x.\n", hr);
276 new_width = mode_desc.Width;
277 new_height = mode_desc.Height;
280 state->fullscreen = TRUE;
281 if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
283 unsigned int new_x = (old_monitor_rect->left >= 0)
284 ? old_monitor_rect->left : old_monitor_rect->right - new_width;
285 unsigned new_y = (old_monitor_rect->top >= 0)
286 ? old_monitor_rect->top : old_monitor_rect->bottom - new_height;
287 RECT new_monitor_rect = {0, 0, new_width, new_height};
288 OffsetRect(&new_monitor_rect, new_x, new_y);
290 SetRect(&state->fullscreen_state.client_rect, 0, 0, new_width, new_height);
291 state->fullscreen_state.monitor_rect = new_monitor_rect;
292 state->fullscreen_state.window_rect = new_monitor_rect;
294 if (target)
295 state->target = target;
297 else
299 state->fullscreen_state.window_rect = *old_monitor_rect;
300 SetRect(&state->fullscreen_state.client_rect, 0, 0,
301 old_monitor_rect->right - old_monitor_rect->left,
302 old_monitor_rect->bottom - old_monitor_rect->top);
306 static IDXGIDevice *create_device(void)
308 IDXGIDevice *dxgi_device;
309 ID3D10Device *device;
310 HRESULT hr;
312 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &device)))
313 goto success;
314 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_WARP, NULL, 0, D3D10_SDK_VERSION, &device)))
315 goto success;
316 if (SUCCEEDED(D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL, 0, D3D10_SDK_VERSION, &device)))
317 goto success;
319 return NULL;
321 success:
322 hr = ID3D10Device_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
323 ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice\n");
324 ID3D10Device_Release(device);
326 return dxgi_device;
329 static void test_adapter_desc(void)
331 DXGI_ADAPTER_DESC1 desc1;
332 IDXGIAdapter1 *adapter1;
333 DXGI_ADAPTER_DESC desc;
334 IDXGIAdapter *adapter;
335 IDXGIDevice *device;
336 ULONG refcount;
337 HRESULT hr;
339 if (!(device = create_device()))
341 skip("Failed to create device, skipping tests.\n");
342 return;
345 hr = IDXGIDevice_GetAdapter(device, &adapter);
346 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
348 hr = IDXGIAdapter_GetDesc(adapter, NULL);
349 ok(hr == E_INVALIDARG, "GetDesc returned %#x, expected %#x.\n",
350 hr, E_INVALIDARG);
352 hr = IDXGIAdapter_GetDesc(adapter, &desc);
353 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
355 trace("%s.\n", wine_dbgstr_w(desc.Description));
356 trace("%04x: %04x:%04x (rev %02x).\n",
357 desc.SubSysId, desc.VendorId, desc.DeviceId, desc.Revision);
358 trace("Dedicated video memory: %lu (%lu MB).\n",
359 desc.DedicatedVideoMemory, desc.DedicatedVideoMemory / (1024 * 1024));
360 trace("Dedicated system memory: %lu (%lu MB).\n",
361 desc.DedicatedSystemMemory, desc.DedicatedSystemMemory / (1024 * 1024));
362 trace("Shared system memory: %lu (%lu MB).\n",
363 desc.SharedSystemMemory, desc.SharedSystemMemory / (1024 * 1024));
364 trace("LUID: %08x:%08x.\n", desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart);
366 hr = IDXGIAdapter_QueryInterface(adapter, &IID_IDXGIAdapter1, (void **)&adapter1);
367 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE), "Got unexpected hr %#x.\n", hr);
368 if (hr == E_NOINTERFACE)
369 goto done;
371 hr = IDXGIAdapter1_GetDesc1(adapter1, &desc1);
372 ok(SUCCEEDED(hr), "GetDesc1 failed, hr %#x.\n", hr);
374 ok(!lstrcmpW(desc.Description, desc1.Description),
375 "Got unexpected description %s.\n", wine_dbgstr_w(desc1.Description));
376 ok(desc1.VendorId == desc.VendorId, "Got unexpected vendor ID %04x.\n", desc1.VendorId);
377 ok(desc1.DeviceId == desc.DeviceId, "Got unexpected device ID %04x.\n", desc1.DeviceId);
378 ok(desc1.SubSysId == desc.SubSysId, "Got unexpected sub system ID %04x.\n", desc1.SubSysId);
379 ok(desc1.Revision == desc.Revision, "Got unexpected revision %02x.\n", desc1.Revision);
380 ok(desc1.DedicatedVideoMemory == desc.DedicatedVideoMemory,
381 "Got unexpected dedicated video memory %lu.\n", desc1.DedicatedVideoMemory);
382 ok(desc1.DedicatedSystemMemory == desc.DedicatedSystemMemory,
383 "Got unexpected dedicated system memory %lu.\n", desc1.DedicatedSystemMemory);
384 ok(desc1.SharedSystemMemory == desc.SharedSystemMemory,
385 "Got unexpected shared system memory %lu.\n", desc1.SharedSystemMemory);
386 ok(!memcmp(&desc.AdapterLuid, &desc1.AdapterLuid, sizeof(desc.AdapterLuid)),
387 "Got unexpected adapter LUID %08x:%08x.\n", desc1.AdapterLuid.HighPart, desc1.AdapterLuid.LowPart);
388 trace("Flags: %08x.\n", desc1.Flags);
390 IDXGIAdapter1_Release(adapter1);
392 done:
393 IDXGIAdapter_Release(adapter);
394 refcount = IDXGIDevice_Release(device);
395 ok(!refcount, "Device has %u references left.\n", refcount);
398 static void test_check_interface_support(void)
400 LARGE_INTEGER driver_version;
401 IDXGIAdapter *adapter;
402 IDXGIDevice *device;
403 IUnknown *iface;
404 ULONG refcount;
405 HRESULT hr;
407 if (!(device = create_device()))
409 skip("Failed to create device.\n");
410 return;
413 hr = IDXGIDevice_GetAdapter(device, &adapter);
414 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
416 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, NULL);
417 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
418 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, &driver_version);
419 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
421 trace("UMD version: %u.%u.%u.%u.\n",
422 HIWORD(U(driver_version).HighPart), LOWORD(U(driver_version).HighPart),
423 HIWORD(U(driver_version).LowPart), LOWORD(U(driver_version).LowPart));
425 hr = IDXGIDevice_QueryInterface(device, &IID_ID3D10Device1, (void **)&iface);
426 if (SUCCEEDED(hr))
428 IUnknown_Release(iface);
429 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, NULL);
430 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
431 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, &driver_version);
432 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
434 else
436 win_skip("D3D10.1 is not supported.\n");
439 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, NULL);
440 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
441 driver_version.HighPart = driver_version.LowPart = 0xdeadbeef;
442 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, &driver_version);
443 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
444 ok(driver_version.HighPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.HighPart);
445 ok(driver_version.LowPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.LowPart);
447 IDXGIAdapter_Release(adapter);
448 refcount = IDXGIDevice_Release(device);
449 ok(!refcount, "Device has %u references left.\n", refcount);
452 static void test_create_surface(void)
454 DXGI_SURFACE_DESC desc;
455 IDXGISurface *surface;
456 IDXGIDevice *device;
457 IUnknown *surface1;
458 IUnknown *texture;
459 ULONG refcount;
460 HRESULT hr;
462 if (!(device = create_device()))
464 skip("Failed to create device, skipping tests.\n");
465 return;
468 desc.Width = 512;
469 desc.Height = 512;
470 desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
471 desc.SampleDesc.Count = 1;
472 desc.SampleDesc.Quality = 0;
474 hr = IDXGIDevice_CreateSurface(device, &desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
475 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
477 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Texture2D, (void **)&texture);
478 ok(SUCCEEDED(hr), "Surface should implement ID3D10Texture2D\n");
479 IUnknown_Release(texture);
481 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture);
482 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
483 "Surface should implement ID3D11Texture2D.\n");
484 if (SUCCEEDED(hr)) IUnknown_Release(texture);
486 hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface1, (void **)&surface1);
487 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
488 "Surface should implement IDXGISurface1.\n");
489 if (SUCCEEDED(hr)) IUnknown_Release(surface1);
491 IDXGISurface_Release(surface);
492 refcount = IDXGIDevice_Release(device);
493 ok(!refcount, "Device has %u references left.\n", refcount);
496 static void test_parents(void)
498 DXGI_SURFACE_DESC surface_desc;
499 IDXGISurface *surface;
500 IDXGIFactory *factory;
501 IDXGIAdapter *adapter;
502 IDXGIDevice *device;
503 IDXGIOutput *output;
504 IUnknown *parent;
505 ULONG refcount;
506 HRESULT hr;
508 if (!(device = create_device()))
510 skip("Failed to create device, skipping tests.\n");
511 return;
514 surface_desc.Width = 512;
515 surface_desc.Height = 512;
516 surface_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
517 surface_desc.SampleDesc.Count = 1;
518 surface_desc.SampleDesc.Quality = 0;
520 hr = IDXGIDevice_CreateSurface(device, &surface_desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
521 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
523 hr = IDXGISurface_GetParent(surface, &IID_IDXGIDevice, (void **)&parent);
524 IDXGISurface_Release(surface);
525 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
526 ok(parent == (IUnknown *)device, "Got parent %p, expected %p.\n", parent, device);
527 IUnknown_Release(parent);
529 hr = IDXGIDevice_GetAdapter(device, &adapter);
530 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
532 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
533 if (hr == DXGI_ERROR_NOT_FOUND)
535 skip("Adapter has not outputs, skipping output tests.\n");
537 else
539 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
541 hr = IDXGIOutput_GetParent(output, &IID_IDXGIAdapter, (void **)&parent);
542 IDXGIOutput_Release(output);
543 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
544 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
545 IUnknown_Release(parent);
548 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
549 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
551 hr = IDXGIFactory_GetParent(factory, &IID_IUnknown, (void **)&parent);
552 ok(hr == E_NOINTERFACE, "GetParent returned %#x, expected %#x.\n", hr, E_NOINTERFACE);
553 ok(parent == NULL, "Got parent %p, expected %p.\n", parent, NULL);
554 IDXGIFactory_Release(factory);
556 hr = IDXGIDevice_GetParent(device, &IID_IDXGIAdapter, (void **)&parent);
557 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
558 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
559 IUnknown_Release(parent);
561 IDXGIAdapter_Release(adapter);
562 refcount = IDXGIDevice_Release(device);
563 ok(!refcount, "Device has %u references left.\n", refcount);
566 static void test_output(void)
568 IDXGIAdapter *adapter;
569 IDXGIDevice *device;
570 HRESULT hr;
571 IDXGIOutput *output;
572 ULONG refcount;
573 UINT mode_count, mode_count_comp, i;
574 DXGI_MODE_DESC *modes;
576 if (!(device = create_device()))
578 skip("Failed to create device, skipping tests.\n");
579 return;
582 hr = IDXGIDevice_GetAdapter(device, &adapter);
583 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
585 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
586 if (hr == DXGI_ERROR_NOT_FOUND)
588 skip("Adapter doesn't have any outputs, skipping tests.\n");
589 IDXGIAdapter_Release(adapter);
590 IDXGIDevice_Release(device);
591 return;
593 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
595 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NULL, NULL);
596 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
598 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
599 ok(SUCCEEDED(hr)
600 || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Remote Desktop Services / Win 7 testbot */
601 "Failed to list modes, hr %#x.\n", hr);
602 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
604 win_skip("GetDisplayModeList() not supported.\n");
605 IDXGIOutput_Release(output);
606 IDXGIAdapter_Release(adapter);
607 IDXGIDevice_Release(device);
608 return;
610 mode_count_comp = mode_count;
612 hr = IDXGIOutput_GetDisplayModeList(output, 0, 0, &mode_count, NULL);
613 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
614 ok(!mode_count, "Got unexpected mode_count %u.\n", mode_count);
616 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
617 DXGI_ENUM_MODES_SCALING, &mode_count, NULL);
618 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
619 ok(mode_count >= mode_count_comp, "Got unexpected mode_count %u, expected >= %u.\n", mode_count, mode_count_comp);
620 mode_count_comp = mode_count;
622 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * (mode_count + 10));
624 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
625 DXGI_ENUM_MODES_SCALING, NULL, modes);
626 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
627 ok(!modes[0].Height, "No output was expected.\n");
629 mode_count = 0;
630 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
631 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
632 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
633 ok(!modes[0].Height, "No output was expected.\n");
635 mode_count = mode_count_comp;
636 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
637 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
638 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
639 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
641 for (i = 0; i < mode_count; i++)
643 ok(modes[i].Height && modes[i].Width, "Proper mode was expected\n");
646 mode_count += 5;
647 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
648 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
649 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
650 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
652 if (mode_count_comp)
654 mode_count = mode_count_comp - 1;
655 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
656 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
657 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
658 ok(mode_count == mode_count_comp - 1, "Got unexpected mode_count %u, expected %u.\n",
659 mode_count, mode_count_comp - 1);
661 else
663 skip("Not enough modes for test, skipping.\n");
666 HeapFree(GetProcessHeap(), 0, modes);
667 IDXGIOutput_Release(output);
668 IDXGIAdapter_Release(adapter);
669 refcount = IDXGIDevice_Release(device);
670 ok(!refcount, "Device has %u references left.\n", refcount);
673 static void test_find_closest_matching_mode(void)
675 DXGI_MODE_DESC *modes, mode, matching_mode;
676 unsigned int i, mode_count;
677 IDXGIAdapter *adapter;
678 IDXGIDevice *device;
679 IDXGIOutput *output;
680 ULONG refcount;
681 HRESULT hr;
683 if (!(device = create_device()))
685 skip("Failed to create device.\n");
686 return;
689 hr = IDXGIDevice_GetAdapter(device, &adapter);
690 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
692 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
693 if (hr == DXGI_ERROR_NOT_FOUND)
695 win_skip("Adapter doesn't have any outputs.\n");
696 IDXGIAdapter_Release(adapter);
697 IDXGIDevice_Release(device);
698 return;
700 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
702 memset(&mode, 0, sizeof(mode));
703 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
704 ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
705 "Got unexpected hr %#x.\n", hr);
706 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
708 win_skip("FindClosestMatchingMode() not supported.\n");
709 goto done;
712 memset(&mode, 0, sizeof(mode));
713 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, (IUnknown *)device);
714 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
716 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
717 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
719 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
721 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
722 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
724 for (i = 0; i < mode_count; ++i)
726 mode = modes[i];
727 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
728 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
729 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING);
731 mode.Format = DXGI_FORMAT_UNKNOWN;
732 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
733 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
735 mode = modes[i];
736 mode.Width = 0;
737 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
738 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
740 mode = modes[i];
741 mode.Height = 0;
742 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
743 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
745 mode = modes[i];
746 mode.Width = mode.Height = 0;
747 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
748 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
749 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_RESOLUTION);
750 ok(matching_mode.Width > 0 && matching_mode.Height > 0, "Got unexpected resolution %ux%u.\n",
751 matching_mode.Width, matching_mode.Height);
753 mode = modes[i];
754 mode.RefreshRate.Numerator = mode.RefreshRate.Denominator = 0;
755 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
756 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
757 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_REFRESH_RATE);
758 ok(matching_mode.RefreshRate.Numerator > 0 && matching_mode.RefreshRate.Denominator > 0,
759 "Got unexpected refresh rate %u / %u.\n",
760 matching_mode.RefreshRate.Numerator, matching_mode.RefreshRate.Denominator);
762 mode = modes[i];
763 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
764 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
765 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
766 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_SCANLINE_ORDERING);
767 ok(matching_mode.ScanlineOrdering, "Got unexpected scanline ordering %#x.\n",
768 matching_mode.ScanlineOrdering);
770 memset(&mode, 0, sizeof(mode));
771 mode.Width = modes[i].Width;
772 mode.Height = modes[i].Height;
773 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
774 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
775 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
776 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
778 memset(&mode, 0, sizeof(mode));
779 mode.Width = modes[i].Width - 1;
780 mode.Height = modes[i].Height - 1;
781 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
782 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
783 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
784 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
786 memset(&mode, 0, sizeof(mode));
787 mode.Width = modes[i].Width + 1;
788 mode.Height = modes[i].Height + 1;
789 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
790 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
791 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
792 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
795 memset(&mode, 0, sizeof(mode));
796 mode.Width = mode.Height = 10;
797 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
798 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
799 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
800 /* Find mode for the lowest resolution. */
801 mode = modes[0];
802 for (i = 0; i < mode_count; ++i)
804 if (mode.Width >= modes[i].Width && mode.Height >= modes[i].Height)
805 mode = modes[i];
807 check_mode_desc(&matching_mode, &mode, MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
809 memset(&mode, 0, sizeof(mode));
810 mode.Width = modes[0].Width;
811 mode.Height = modes[0].Height;
812 mode.Format = modes[0].Format;
813 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST;
814 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
815 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
816 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
818 memset(&mode, 0, sizeof(mode));
819 mode.Width = modes[0].Width;
820 mode.Height = modes[0].Height;
821 mode.Format = modes[0].Format;
822 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST;
823 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
824 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
825 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
827 memset(&mode, 0, sizeof(mode));
828 mode.Width = modes[0].Width;
829 mode.Height = modes[0].Height;
830 mode.Format = modes[0].Format;
831 mode.Scaling = DXGI_MODE_SCALING_CENTERED;
832 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
833 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
834 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
836 memset(&mode, 0, sizeof(mode));
837 mode.Width = modes[0].Width;
838 mode.Height = modes[0].Height;
839 mode.Format = modes[0].Format;
840 mode.Scaling = DXGI_MODE_SCALING_STRETCHED;
841 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
842 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
843 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
845 HeapFree(GetProcessHeap(), 0, modes);
847 done:
848 IDXGIOutput_Release(output);
849 IDXGIAdapter_Release(adapter);
850 refcount = IDXGIDevice_Release(device);
851 ok(!refcount, "Device has %u references left.\n", refcount);
854 struct refresh_rates
856 UINT numerator;
857 UINT denominator;
858 BOOL numerator_should_pass;
859 BOOL denominator_should_pass;
862 static void test_create_swapchain(void)
864 struct swapchain_fullscreen_state initial_state, expected_state;
865 unsigned int i, expected_width, expected_height;
866 DXGI_SWAP_CHAIN_DESC creation_desc, result_desc;
867 ULONG refcount, expected_refcount;
868 RECT *expected_client_rect;
869 IDXGISwapChain *swapchain;
870 IUnknown *obj, *parent;
871 IDXGIAdapter *adapter;
872 IDXGIFactory *factory;
873 IDXGIDevice *device;
874 IDXGIOutput *target;
875 BOOL fullscreen;
876 HRESULT hr;
878 const struct refresh_rates refresh_list[] =
880 {60, 60, FALSE, FALSE},
881 {60, 0, TRUE, FALSE},
882 {60, 1, TRUE, TRUE},
883 { 0, 60, TRUE, FALSE},
884 { 0, 0, TRUE, FALSE},
887 if (!(device = create_device()))
889 skip("Failed to create device, skipping tests.\n");
890 return;
893 creation_desc.OutputWindow = 0;
894 creation_desc.BufferDesc.Width = 800;
895 creation_desc.BufferDesc.Height = 600;
896 creation_desc.BufferDesc.RefreshRate.Numerator = 60;
897 creation_desc.BufferDesc.RefreshRate.Denominator = 60;
898 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
899 creation_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
900 creation_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
901 creation_desc.SampleDesc.Count = 1;
902 creation_desc.SampleDesc.Quality = 0;
903 creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
904 creation_desc.BufferCount = 1;
905 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
906 creation_desc.Windowed = TRUE;
907 creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
908 creation_desc.Flags = 0;
910 memset(&initial_state, 0, sizeof(initial_state));
911 capture_fullscreen_state(&initial_state.fullscreen_state, creation_desc.OutputWindow);
913 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
914 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
916 hr = IDXGIDevice_GetAdapter(device, &adapter);
917 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
919 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
920 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
922 expected_refcount = get_refcount((IUnknown *)adapter);
923 refcount = get_refcount((IUnknown *)factory);
924 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
925 refcount = get_refcount((IUnknown *)device);
926 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
928 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
929 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
931 refcount = get_refcount((IUnknown *)adapter);
932 ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount);
933 refcount = get_refcount((IUnknown *)factory);
934 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
935 refcount = get_refcount((IUnknown *)device);
936 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
938 hr = IDXGISwapChain_GetDesc(swapchain, NULL);
939 ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr);
941 hr = IDXGISwapChain_GetParent(swapchain, &IID_IUnknown, (void **)&parent);
942 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
943 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
944 refcount = IUnknown_Release(parent);
945 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
947 hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent);
948 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
949 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
950 refcount = IUnknown_Release(parent);
951 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
953 IDXGISwapChain_Release(swapchain);
955 refcount = get_refcount((IUnknown *)factory);
956 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
958 for (i = 0; i < sizeof(refresh_list) / sizeof(*refresh_list); ++i)
960 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
961 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
963 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
964 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
966 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
967 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
969 ok(result_desc.Windowed == creation_desc.Windowed, "Test %u: Got unexpected windowed %#x.\n",
970 i, result_desc.Windowed);
972 todo_wine_if (!refresh_list[i].numerator_should_pass)
973 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
974 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
976 todo_wine_if (!refresh_list[i].denominator_should_pass)
977 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
978 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
980 fullscreen = 0xdeadbeef;
981 target = (void *)0xdeadbeef;
982 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
983 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
984 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
985 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
987 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
988 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
989 fullscreen = 0xdeadbeef;
990 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
991 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
992 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
993 target = (void *)0xdeadbeef;
994 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
995 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
996 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
998 check_swapchain_fullscreen_state(swapchain, &initial_state);
999 IDXGISwapChain_Release(swapchain);
1002 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1004 creation_desc.Windowed = FALSE;
1006 for (i = 0; i < sizeof(refresh_list) / sizeof(*refresh_list); ++i)
1008 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
1009 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
1011 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1012 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
1014 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1015 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
1017 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1018 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1019 if (result_desc.Windowed != creation_desc.Windowed)
1020 trace("Test %u: Failed to change fullscreen state.\n", i);
1022 todo_wine_if (!refresh_list[i].numerator_should_pass)
1023 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
1024 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
1026 todo_wine_if (!refresh_list[i].denominator_should_pass)
1027 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
1028 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
1030 fullscreen = FALSE;
1031 target = NULL;
1032 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1033 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1034 ok(fullscreen == !result_desc.Windowed, "Test %u: Got fullscreen %#x, expected %#x.\n",
1035 i, fullscreen, result_desc.Windowed);
1036 ok(result_desc.Windowed ? !target : !!target, "Test %u: Got unexpected target %p.\n", i, target);
1037 if (!result_desc.Windowed)
1039 IDXGIOutput *containing_output;
1040 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1041 ok(SUCCEEDED(hr), "Test %u: GetContainingOutput failed, hr %#x.\n", i, hr);
1042 ok(containing_output == target, "Test %u: Got unexpected containing output pointer %p.\n",
1043 i, containing_output);
1044 IDXGIOutput_Release(containing_output);
1046 ok(output_belongs_to_adapter(target, adapter),
1047 "Test %u: Output %p doesn't belong to adapter %p.\n",
1048 i, target, adapter);
1049 IDXGIOutput_Release(target);
1051 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
1052 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1053 fullscreen = FALSE;
1054 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1055 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1056 ok(fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1057 target = NULL;
1058 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1059 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1060 ok(!!target, "Test %u: Got unexpected target %p.\n", i, target);
1061 IDXGIOutput_Release(target);
1064 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1065 ok(SUCCEEDED(hr), "Test %u: SetFullscreenState failed, hr %#x.\n", i, hr);
1067 fullscreen = 0xdeadbeef;
1068 target = (void *)0xdeadbeef;
1069 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1070 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1071 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1072 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1074 check_swapchain_fullscreen_state(swapchain, &initial_state);
1075 IDXGISwapChain_Release(swapchain);
1078 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1080 /* Test swapchain creation with backbuffer width and height equal to 0. */
1081 expected_state = initial_state;
1082 expected_client_rect = &expected_state.fullscreen_state.client_rect;
1084 /* Windowed */
1085 expected_width = expected_client_rect->right;
1086 expected_height = expected_client_rect->bottom;
1088 creation_desc.BufferDesc.Width = 0;
1089 creation_desc.BufferDesc.Height = 0;
1090 creation_desc.Windowed = TRUE;
1091 creation_desc.Flags = 0;
1092 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1093 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1094 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1095 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1096 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1097 result_desc.BufferDesc.Width, expected_width);
1098 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1099 result_desc.BufferDesc.Height, expected_height);
1100 check_swapchain_fullscreen_state(swapchain, &expected_state);
1101 IDXGISwapChain_Release(swapchain);
1103 DestroyWindow(creation_desc.OutputWindow);
1104 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1105 WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
1106 0, 0, 222, 222, 0, 0, 0, 0);
1107 SetRect(&expected_state.fullscreen_state.window_rect, 0, 0, 222, 222);
1108 GetClientRect(creation_desc.OutputWindow, expected_client_rect);
1109 expected_width = expected_client_rect->right;
1110 expected_height = expected_client_rect->bottom;
1112 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1113 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1114 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1115 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1116 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1117 result_desc.BufferDesc.Width, expected_width);
1118 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1119 result_desc.BufferDesc.Height, expected_height);
1120 check_swapchain_fullscreen_state(swapchain, &expected_state);
1121 IDXGISwapChain_Release(swapchain);
1123 DestroyWindow(creation_desc.OutputWindow);
1124 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1125 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1127 /* Fullscreen */
1128 creation_desc.Windowed = FALSE;
1129 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1130 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1131 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1132 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1133 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1134 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1135 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1136 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1137 "GetContainingOutput failed, hr %#x.\n", hr);
1138 check_swapchain_fullscreen_state(swapchain, &initial_state);
1139 IDXGISwapChain_Release(swapchain);
1140 if (hr == DXGI_ERROR_UNSUPPORTED)
1142 win_skip("GetContainingOutput() not supported.\n");
1143 goto done;
1145 if (result_desc.Windowed)
1147 win_skip("Fullscreen not supported.\n");
1148 IDXGIOutput_Release(expected_state.target);
1149 goto done;
1152 creation_desc.BufferDesc.Width = 0;
1153 creation_desc.BufferDesc.Height = 0;
1154 creation_desc.Windowed = FALSE;
1155 creation_desc.Flags = 0;
1156 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1157 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1158 expected_width = expected_client_rect->right - expected_client_rect->left;
1159 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1161 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1162 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1163 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1164 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1165 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1166 result_desc.BufferDesc.Width, expected_width);
1167 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1168 result_desc.BufferDesc.Height, expected_height);
1169 check_swapchain_fullscreen_state(swapchain, &expected_state);
1170 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1171 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1172 check_swapchain_fullscreen_state(swapchain, &initial_state);
1173 IDXGISwapChain_Release(swapchain);
1175 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
1176 creation_desc.BufferDesc.Width = 0;
1177 creation_desc.BufferDesc.Height = 0;
1178 creation_desc.Windowed = FALSE;
1179 creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1180 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1181 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1182 expected_width = expected_client_rect->right - expected_client_rect->left;
1183 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1185 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1186 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1187 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1188 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1189 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1190 result_desc.BufferDesc.Width, expected_width);
1191 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1192 result_desc.BufferDesc.Height, expected_height);
1193 check_swapchain_fullscreen_state(swapchain, &expected_state);
1194 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1195 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1196 check_swapchain_fullscreen_state(swapchain, &initial_state);
1197 IDXGISwapChain_Release(swapchain);
1199 IDXGIOutput_Release(expected_state.target);
1201 done:
1202 IUnknown_Release(obj);
1203 refcount = IDXGIDevice_Release(device);
1204 ok(!refcount, "Device has %u references left.\n", refcount);
1205 refcount = IDXGIAdapter_Release(adapter);
1206 ok(!refcount, "Adapter has %u references left.\n", refcount);
1207 refcount = IDXGIFactory_Release(factory);
1208 ok(!refcount, "Factory has %u references left.\n", refcount);
1209 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1210 DestroyWindow(creation_desc.OutputWindow);
1213 static void test_get_containing_output(void)
1215 unsigned int output_count, output_idx;
1216 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1217 IDXGIOutput *output, *output2;
1218 DXGI_OUTPUT_DESC output_desc;
1219 MONITORINFOEXW monitor_info;
1220 IDXGISwapChain *swapchain;
1221 IDXGIFactory *factory;
1222 IDXGIAdapter *adapter;
1223 POINT points[4 * 16];
1224 IDXGIDevice *device;
1225 unsigned int i, j;
1226 HMONITOR monitor;
1227 ULONG refcount;
1228 HRESULT hr;
1229 BOOL ret;
1231 if (!(device = create_device()))
1233 skip("Failed to create device.\n");
1234 return;
1237 hr = IDXGIDevice_GetAdapter(device, &adapter);
1238 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1240 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1241 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1243 swapchain_desc.BufferDesc.Width = 100;
1244 swapchain_desc.BufferDesc.Height = 100;
1245 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1246 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1247 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1248 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1249 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1250 swapchain_desc.SampleDesc.Count = 1;
1251 swapchain_desc.SampleDesc.Quality = 0;
1252 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1253 swapchain_desc.BufferCount = 1;
1254 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1255 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1256 swapchain_desc.Windowed = TRUE;
1257 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1258 swapchain_desc.Flags = 0;
1260 output_count = 0;
1261 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1263 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_count, hr);
1264 IDXGIOutput_Release(output);
1265 ++output_count;
1268 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1269 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1271 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, 0);
1272 ok(!!monitor, "MonitorFromWindow failed.\n");
1274 monitor_info.cbSize = sizeof(monitor_info);
1275 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1276 ok(ret, "Failed to get monitor info.\n");
1278 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1279 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1280 "GetContainingOutput failed, hr %#x.\n", hr);
1281 if (hr == DXGI_ERROR_UNSUPPORTED)
1283 win_skip("GetContainingOutput() not supported.\n");
1284 IDXGISwapChain_Release(swapchain);
1285 goto done;
1288 hr = IDXGIOutput_GetDesc(output, &output_desc);
1289 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1291 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1292 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1293 ok(output != output2, "Got unexpected output pointers %p, %p.\n", output, output2);
1294 check_output_equal(output, output2);
1296 refcount = IDXGIOutput_Release(output);
1297 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1298 refcount = IDXGIOutput_Release(output2);
1299 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1301 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1302 "Got unexpected device name %s, expected %s.\n",
1303 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1304 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1305 "Got unexpected desktop coordinates %s, expected %s.\n",
1306 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1307 wine_dbgstr_rect(&monitor_info.rcMonitor));
1309 output_idx = 0;
1310 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1312 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1314 hr = IDXGIOutput_GetDesc(output, &output_desc);
1315 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1317 /* Move the OutputWindow to the current output. */
1318 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
1319 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
1320 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1321 ok(ret, "SetWindowPos failed.\n");
1323 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1324 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1326 check_output_equal(output, output2);
1328 refcount = IDXGIOutput_Release(output2);
1329 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1330 refcount = IDXGIOutput_Release(output);
1331 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1332 ++output_idx;
1334 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
1335 for (i = 0; i < 4; ++i)
1337 static const POINT offsets[] =
1339 { 0, 0},
1340 {-49, 0}, {-50, 0}, {-51, 0},
1341 { 0, -49}, { 0, -50}, { 0, -51},
1342 {-49, -49}, {-50, -49}, {-51, -49},
1343 {-49, -50}, {-50, -50}, {-51, -50},
1344 {-49, -51}, {-50, -51}, {-51, -51},
1346 unsigned int x, y;
1348 switch (i)
1350 case 0:
1351 x = output_desc.DesktopCoordinates.left;
1352 y = output_desc.DesktopCoordinates.top;
1353 break;
1354 case 1:
1355 x = output_desc.DesktopCoordinates.right;
1356 y = output_desc.DesktopCoordinates.top;
1357 break;
1358 case 2:
1359 x = output_desc.DesktopCoordinates.right;
1360 y = output_desc.DesktopCoordinates.bottom;
1361 break;
1362 case 3:
1363 x = output_desc.DesktopCoordinates.left;
1364 y = output_desc.DesktopCoordinates.bottom;
1365 break;
1368 for (j = 0; j < sizeof(offsets) / sizeof(*offsets); ++j)
1370 unsigned int idx = (sizeof(offsets) / sizeof(*offsets)) * i + j;
1371 assert(idx < sizeof(points) / sizeof(*points));
1372 points[idx].x = x + offsets[j].x;
1373 points[idx].y = y + offsets[j].y;
1377 for (i = 0; i < sizeof(points) / sizeof(*points); ++i)
1379 ret = SetWindowPos(swapchain_desc.OutputWindow, 0, points[i].x, points[i].y,
1380 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1381 ok(ret, "SetWindowPos failed.\n");
1383 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, MONITOR_DEFAULTTONEAREST);
1384 ok(!!monitor, "MonitorFromWindow failed.\n");
1386 monitor_info.cbSize = sizeof(monitor_info);
1387 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1388 ok(ret, "Failed to get monitor info.\n");
1390 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1391 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1392 ok(!!output, "Got unexpected containing output %p.\n", output);
1393 hr = IDXGIOutput_GetDesc(output, &output_desc);
1394 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1395 refcount = IDXGIOutput_Release(output);
1396 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1398 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1399 "Got unexpected device name %s, expected %s.\n",
1400 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1401 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1402 "Got unexpected desktop coordinates %s, expected %s.\n",
1403 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1404 wine_dbgstr_rect(&monitor_info.rcMonitor));
1408 refcount = IDXGISwapChain_Release(swapchain);
1409 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1411 done:
1412 refcount = IDXGIDevice_Release(device);
1413 ok(!refcount, "Device has %u references left.\n", refcount);
1414 refcount = IDXGIAdapter_Release(adapter);
1415 ok(!refcount, "Adapter has %u references left.\n", refcount);
1416 refcount = IDXGIFactory_Release(factory);
1417 ok(!refcount, "Factory has %u references left.\n", refcount);
1418 DestroyWindow(swapchain_desc.OutputWindow);
1421 static void test_swapchain_fullscreen_state(IDXGISwapChain *swapchain,
1422 IDXGIAdapter *adapter, const struct swapchain_fullscreen_state *initial_state)
1424 MONITORINFOEXW monitor_info, *output_monitor_info;
1425 struct swapchain_fullscreen_state expected_state;
1426 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1427 DXGI_OUTPUT_DESC output_desc;
1428 unsigned int i, output_count;
1429 IDXGIOutput *output;
1430 HRESULT hr;
1431 BOOL ret;
1433 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1434 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1436 check_swapchain_fullscreen_state(swapchain, initial_state);
1438 expected_state = *initial_state;
1439 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1440 &swapchain_desc, &initial_state->fullscreen_state.monitor_rect, 800, 600, NULL);
1441 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1442 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1444 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1445 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1446 check_swapchain_fullscreen_state(swapchain, &expected_state);
1448 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1449 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1450 check_swapchain_fullscreen_state(swapchain, &expected_state);
1452 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1453 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1454 check_swapchain_fullscreen_state(swapchain, initial_state);
1456 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1457 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1458 check_swapchain_fullscreen_state(swapchain, initial_state);
1460 IDXGIOutput_Release(expected_state.target);
1461 expected_state.target = NULL;
1463 output_count = 0;
1464 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1466 IDXGIOutput_Release(output);
1467 ++output_count;
1470 output_monitor_info = HeapAlloc(GetProcessHeap(), 0, output_count * sizeof(*output_monitor_info));
1471 ok(!!output_monitor_info, "Failed to allocate memory.\n");
1472 for (i = 0; i < output_count; ++i)
1474 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1475 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1477 hr = IDXGIOutput_GetDesc(output, &output_desc);
1478 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1480 output_monitor_info[i].cbSize = sizeof(*output_monitor_info);
1481 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&output_monitor_info[i]);
1482 ok(ret, "Failed to get monitor info.\n");
1484 IDXGIOutput_Release(output);
1487 for (i = 0; i < output_count; ++i)
1489 RECT orig_monitor_rect = output_monitor_info[i].rcMonitor;
1490 IDXGIOutput *target;
1491 BOOL fullscreen;
1493 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1494 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1495 hr = IDXGIOutput_GetDesc(output, &output_desc);
1496 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1498 expected_state = *initial_state;
1499 expected_state.target = output;
1500 expected_state.fullscreen_state.monitor = output_desc.Monitor;
1501 expected_state.fullscreen_state.monitor_rect = orig_monitor_rect;
1502 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1503 &swapchain_desc, &orig_monitor_rect, 800, 600, NULL);
1505 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1506 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1507 check_swapchain_fullscreen_state(swapchain, &expected_state);
1509 target = NULL;
1510 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1511 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1512 ok(target == output, "Got target pointer %p, expected %p.\n", target, output);
1513 IDXGIOutput_Release(target);
1514 fullscreen = FALSE;
1515 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1516 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1517 ok(fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1519 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1520 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1521 check_swapchain_fullscreen_state(swapchain, &expected_state);
1522 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, output);
1523 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1524 check_swapchain_fullscreen_state(swapchain, &expected_state);
1525 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1526 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1527 check_swapchain_fullscreen_state(swapchain, initial_state);
1529 fullscreen = TRUE;
1530 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1531 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1532 ok(!fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1534 check_swapchain_fullscreen_state(swapchain, initial_state);
1535 monitor_info.cbSize = sizeof(monitor_info);
1536 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1537 ok(ret, "Failed to get monitor info.\n");
1538 ok(EqualRect(&monitor_info.rcMonitor, &orig_monitor_rect), "Got monitor rect %s, expected %s.\n",
1539 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&orig_monitor_rect));
1541 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1542 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1544 IDXGIOutput_Release(output);
1547 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1548 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1549 check_swapchain_fullscreen_state(swapchain, initial_state);
1551 for (i = 0; i < output_count; ++i)
1553 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1554 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1556 hr = IDXGIOutput_GetDesc(output, &output_desc);
1557 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1559 monitor_info.cbSize = sizeof(monitor_info);
1560 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1561 ok(ret, "Failed to get monitor info.\n");
1563 ok(EqualRect(&monitor_info.rcMonitor, &output_monitor_info[i].rcMonitor),
1564 "Got monitor rect %s, expected %s.\n",
1565 wine_dbgstr_rect(&monitor_info.rcMonitor),
1566 wine_dbgstr_rect(&output_monitor_info[i].rcMonitor));
1568 IDXGIOutput_Release(output);
1571 HeapFree(GetProcessHeap(), 0, output_monitor_info);
1574 static void test_set_fullscreen(void)
1576 struct swapchain_fullscreen_state initial_state;
1577 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1578 IDXGISwapChain *swapchain;
1579 IDXGIFactory *factory;
1580 IDXGIAdapter *adapter;
1581 IDXGIDevice *device;
1582 ULONG refcount;
1583 HRESULT hr;
1585 if (!(device = create_device()))
1587 skip("Failed to create device.\n");
1588 return;
1591 hr = IDXGIDevice_GetAdapter(device, &adapter);
1592 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1594 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1595 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1597 swapchain_desc.BufferDesc.Width = 800;
1598 swapchain_desc.BufferDesc.Height = 600;
1599 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1600 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1601 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1602 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1603 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1604 swapchain_desc.SampleDesc.Count = 1;
1605 swapchain_desc.SampleDesc.Quality = 0;
1606 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1607 swapchain_desc.BufferCount = 1;
1608 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1609 swapchain_desc.Windowed = TRUE;
1610 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1611 swapchain_desc.Flags = 0;
1613 memset(&initial_state, 0, sizeof(initial_state));
1614 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
1615 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1616 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1617 check_swapchain_fullscreen_state(swapchain, &initial_state);
1618 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1619 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, "SetFullscreenState failed, hr %#x.\n", hr);
1620 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
1622 skip("Could not change fullscreen state.\n");
1623 goto done;
1625 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1626 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1627 refcount = IDXGISwapChain_Release(swapchain);
1628 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1630 DestroyWindow(swapchain_desc.OutputWindow);
1631 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1632 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1633 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1634 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1635 check_swapchain_fullscreen_state(swapchain, &initial_state);
1636 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1637 refcount = IDXGISwapChain_Release(swapchain);
1638 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1640 DestroyWindow(swapchain_desc.OutputWindow);
1641 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1642 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1643 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1644 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1645 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1646 check_swapchain_fullscreen_state(swapchain, &initial_state);
1647 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1649 done:
1650 refcount = IDXGISwapChain_Release(swapchain);
1651 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1652 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1653 DestroyWindow(swapchain_desc.OutputWindow);
1655 IDXGIAdapter_Release(adapter);
1656 refcount = IDXGIDevice_Release(device);
1657 ok(!refcount, "Device has %u references left.\n", refcount);
1658 refcount = IDXGIFactory_Release(factory);
1659 ok(!refcount, "Factory has %u references left.\n", refcount);
1662 static void test_default_fullscreen_target_output(void)
1664 IDXGIOutput *output, *containing_output, *target;
1665 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1666 DXGI_OUTPUT_DESC output_desc;
1667 IDXGISwapChain *swapchain;
1668 unsigned int output_idx;
1669 IDXGIFactory *factory;
1670 IDXGIAdapter *adapter;
1671 IDXGIDevice *device;
1672 ULONG refcount;
1673 HRESULT hr;
1674 BOOL ret;
1676 if (!(device = create_device()))
1678 skip("Failed to create device.\n");
1679 return;
1682 hr = IDXGIDevice_GetAdapter(device, &adapter);
1683 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1685 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1686 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1688 swapchain_desc.BufferDesc.Width = 100;
1689 swapchain_desc.BufferDesc.Height = 100;
1690 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1691 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1692 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1693 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1694 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1695 swapchain_desc.SampleDesc.Count = 1;
1696 swapchain_desc.SampleDesc.Quality = 0;
1697 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1698 swapchain_desc.BufferCount = 1;
1699 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1700 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1701 swapchain_desc.Windowed = TRUE;
1702 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1703 swapchain_desc.Flags = 0;
1705 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1706 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1708 output_idx = 0;
1709 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1711 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1713 hr = IDXGIOutput_GetDesc(output, &output_desc);
1714 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1716 /* Move the OutputWindow to the current output. */
1717 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
1718 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
1719 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1720 ok(ret, "SetWindowPos failed.\n");
1722 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1723 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1724 "GetContainingOutput failed, hr %#x.\n", hr);
1725 if (hr == DXGI_ERROR_UNSUPPORTED)
1727 win_skip("GetContainingOutput() not supported.\n");
1728 IDXGIOutput_Release(output);
1729 goto done;
1732 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1733 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
1734 "SetFullscreenState failed, hr %#x.\n", hr);
1735 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
1737 skip("Could not change fullscreen state.\n");
1738 IDXGIOutput_Release(containing_output);
1739 IDXGIOutput_Release(output);
1740 goto done;
1743 target = NULL;
1744 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1745 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1746 ok(target != containing_output, "Got unexpected output pointers %p, %p.\n",
1747 target, containing_output);
1748 check_output_equal(target, containing_output);
1750 refcount = IDXGIOutput_Release(containing_output);
1751 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1753 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1754 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1755 ok(containing_output == target, "Got unexpected containing output %p, expected %p.\n",
1756 containing_output, target);
1757 refcount = IDXGIOutput_Release(containing_output);
1758 ok(refcount >= 2, "Got unexpected refcount %u.\n", refcount);
1759 refcount = IDXGIOutput_Release(target);
1760 ok(refcount >= 1, "Got unexpected refcount %u.\n", refcount);
1762 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1763 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1765 IDXGIOutput_Release(output);
1766 ++output_idx;
1769 done:
1770 refcount = IDXGISwapChain_Release(swapchain);
1771 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1773 refcount = IDXGIDevice_Release(device);
1774 ok(!refcount, "Device has %u references left.\n", refcount);
1775 refcount = IDXGIAdapter_Release(adapter);
1776 ok(!refcount, "Adapter has %u references left.\n", refcount);
1777 refcount = IDXGIFactory_Release(factory);
1778 ok(!refcount, "Factory has %u references left.\n", refcount);
1779 DestroyWindow(swapchain_desc.OutputWindow);
1782 static void test_windowed_resize_target(IDXGISwapChain *swapchain, HWND window,
1783 struct swapchain_fullscreen_state *state)
1785 struct swapchain_fullscreen_state expected_state;
1786 struct fullscreen_state *e;
1787 DXGI_MODE_DESC mode;
1788 RECT window_rect;
1789 unsigned int i;
1790 HRESULT hr;
1791 BOOL ret;
1793 static const struct
1795 unsigned int width, height;
1797 sizes[] =
1799 {200, 200},
1800 {400, 200},
1801 {400, 400},
1802 {600, 800},
1803 {1000, 600},
1804 {1600, 100},
1805 {2000, 1000},
1808 check_swapchain_fullscreen_state(swapchain, state);
1809 expected_state = *state;
1810 e = &expected_state.fullscreen_state;
1812 for (i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i)
1814 SetRect(&e->client_rect, 0, 0, sizes[i].width, sizes[i].height);
1815 e->window_rect = e->client_rect;
1816 ret = AdjustWindowRectEx(&e->window_rect, GetWindowLongW(window, GWL_STYLE),
1817 FALSE, GetWindowLongW(window, GWL_EXSTYLE));
1818 ok(ret, "AdjustWindowRectEx failed.\n");
1819 if (GetMenu(window))
1820 e->client_rect.bottom -= GetSystemMetrics(SM_CYMENU);
1821 SetRect(&e->window_rect, 0, 0,
1822 e->window_rect.right - e->window_rect.left,
1823 e->window_rect.bottom - e->window_rect.top);
1824 GetWindowRect(window, &window_rect);
1825 OffsetRect(&e->window_rect, window_rect.left, window_rect.top);
1826 if (e->window_rect.right >= e->monitor_rect.right
1827 || e->window_rect.bottom >= e->monitor_rect.bottom)
1829 skip("Test %u: Window %s does not fit on screen %s.\n",
1830 i, wine_dbgstr_rect(&e->window_rect), wine_dbgstr_rect(&e->monitor_rect));
1831 continue;
1834 memset(&mode, 0, sizeof(mode));
1835 mode.Width = sizes[i].width;
1836 mode.Height = sizes[i].height;
1837 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
1838 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1839 check_swapchain_fullscreen_state(swapchain, &expected_state);
1842 ret = MoveWindow(window, 0, 0, 0, 0, TRUE);
1843 ok(ret, "MoveWindow failed.\n");
1844 GetWindowRect(window, &e->window_rect);
1845 GetClientRect(window, &e->client_rect);
1846 ret = MoveWindow(window, 0, 0, 200, 200, TRUE);
1848 memset(&mode, 0, sizeof(mode));
1849 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
1850 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1851 check_swapchain_fullscreen_state(swapchain, &expected_state);
1853 GetWindowRect(window, &e->window_rect);
1854 GetClientRect(window, &e->client_rect);
1855 *state = expected_state;
1858 static void test_fullscreen_resize_target(IDXGISwapChain *swapchain,
1859 const struct swapchain_fullscreen_state *initial_state)
1861 struct swapchain_fullscreen_state expected_state;
1862 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1863 DXGI_OUTPUT_DESC output_desc;
1864 unsigned int i, mode_count;
1865 DXGI_MODE_DESC *modes;
1866 IDXGIOutput *target;
1867 HRESULT hr;
1869 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1870 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1872 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1873 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1875 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
1876 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
1877 "Failed to list modes, hr %#x.\n", hr);
1878 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
1880 win_skip("GetDisplayModeList() not supported.\n");
1881 IDXGIOutput_Release(target);
1882 return;
1885 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
1886 ok(!!modes, "Failed to allocate memory.\n");
1888 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
1889 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
1891 expected_state = *initial_state;
1892 for (i = 0; i < min(mode_count, 20); ++i)
1894 /* FIXME: Modes with scaling aren't fully tested. */
1895 if (!(swapchain_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
1896 && modes[i].Scaling != DXGI_MODE_SCALING_UNSPECIFIED)
1897 continue;
1899 hr = IDXGIOutput_GetDesc(target, &output_desc);
1900 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1902 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1903 &swapchain_desc, &output_desc.DesktopCoordinates, modes[i].Width, modes[i].Height, NULL);
1905 hr = IDXGISwapChain_ResizeTarget(swapchain, &modes[i]);
1906 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1907 check_swapchain_fullscreen_state(swapchain, &expected_state);
1909 hr = IDXGIOutput_GetDesc(target, &output_desc);
1910 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1911 ok(EqualRect(&output_desc.DesktopCoordinates, &expected_state.fullscreen_state.monitor_rect),
1912 "Got desktop coordinates %s, expected %s.\n",
1913 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1914 wine_dbgstr_rect(&expected_state.fullscreen_state.monitor_rect));
1917 HeapFree(GetProcessHeap(), 0, modes);
1918 IDXGIOutput_Release(target);
1921 static void test_resize_target(void)
1923 struct swapchain_fullscreen_state initial_state, expected_state;
1924 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1925 IDXGISwapChain *swapchain;
1926 IDXGIFactory *factory;
1927 IDXGIAdapter *adapter;
1928 IDXGIDevice *device;
1929 unsigned int i;
1930 ULONG refcount;
1931 HRESULT hr;
1933 static const struct
1935 POINT origin;
1936 BOOL fullscreen;
1937 BOOL menu;
1938 unsigned int flags;
1940 tests[] =
1942 {{ 0, 0}, TRUE, FALSE, 0},
1943 {{10, 10}, TRUE, FALSE, 0},
1944 {{ 0, 0}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1945 {{10, 10}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1946 {{ 0, 0}, FALSE, FALSE, 0},
1947 {{ 0, 0}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1948 {{10, 10}, FALSE, FALSE, 0},
1949 {{10, 10}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1950 {{ 0, 0}, FALSE, TRUE, 0},
1951 {{ 0, 0}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1952 {{10, 10}, FALSE, TRUE, 0},
1953 {{10, 10}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1956 if (!(device = create_device()))
1958 skip("Failed to create device.\n");
1959 return;
1962 hr = IDXGIDevice_GetAdapter(device, &adapter);
1963 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1965 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1966 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1968 swapchain_desc.BufferDesc.Width = 800;
1969 swapchain_desc.BufferDesc.Height = 600;
1970 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1971 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
1972 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1973 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1974 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1975 swapchain_desc.SampleDesc.Count = 1;
1976 swapchain_desc.SampleDesc.Quality = 0;
1977 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1978 swapchain_desc.BufferCount = 1;
1979 swapchain_desc.Windowed = TRUE;
1980 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1981 swapchain_desc.Flags = 0;
1983 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
1985 swapchain_desc.Flags = tests[i].flags;
1986 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0,
1987 tests[i].origin.x, tests[i].origin.y, 400, 200, 0, 0, 0, 0);
1988 if (tests[i].menu)
1990 HMENU menu_bar = CreateMenu();
1991 HMENU menu = CreateMenu();
1992 AppendMenuA(menu_bar, MF_POPUP, (UINT_PTR)menu, "Menu");
1993 SetMenu(swapchain_desc.OutputWindow, menu_bar);
1996 memset(&initial_state, 0, sizeof(initial_state));
1997 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
1999 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2000 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2001 check_swapchain_fullscreen_state(swapchain, &initial_state);
2003 expected_state = initial_state;
2004 if (tests[i].fullscreen)
2006 expected_state.fullscreen = TRUE;
2007 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2008 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect, 800, 600, NULL);
2009 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
2010 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2011 "GetContainingOutput failed, hr %#x.\n", hr);
2012 if (hr == DXGI_ERROR_UNSUPPORTED)
2014 win_skip("GetContainingOutput() not supported.\n");
2015 IDXGISwapChain_Release(swapchain);
2016 DestroyWindow(swapchain_desc.OutputWindow);
2017 continue;
2020 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
2021 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
2022 "SetFullscreenState failed, hr %#x.\n", hr);
2023 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
2025 skip("Could not change fullscreen state.\n");
2026 IDXGIOutput_Release(expected_state.target);
2027 IDXGISwapChain_Release(swapchain);
2028 DestroyWindow(swapchain_desc.OutputWindow);
2029 continue;
2032 check_swapchain_fullscreen_state(swapchain, &expected_state);
2034 hr = IDXGISwapChain_ResizeTarget(swapchain, NULL);
2035 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2036 check_swapchain_fullscreen_state(swapchain, &expected_state);
2038 if (tests[i].fullscreen)
2040 test_fullscreen_resize_target(swapchain, &expected_state);
2042 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2043 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2044 check_swapchain_fullscreen_state(swapchain, &initial_state);
2045 IDXGIOutput_Release(expected_state.target);
2046 check_swapchain_fullscreen_state(swapchain, &initial_state);
2047 expected_state = initial_state;
2049 else
2051 test_windowed_resize_target(swapchain, swapchain_desc.OutputWindow, &expected_state);
2053 check_swapchain_fullscreen_state(swapchain, &expected_state);
2056 refcount = IDXGISwapChain_Release(swapchain);
2057 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2058 check_window_fullscreen_state(swapchain_desc.OutputWindow, &expected_state.fullscreen_state);
2059 DestroyWindow(swapchain_desc.OutputWindow);
2062 IDXGIAdapter_Release(adapter);
2063 refcount = IDXGIDevice_Release(device);
2064 ok(!refcount, "Device has %u references left.\n", refcount);
2065 refcount = IDXGIFactory_Release(factory);
2066 ok(!refcount, "Factory has %u references left.\n", refcount);
2069 static void test_inexact_modes(void)
2071 struct swapchain_fullscreen_state initial_state, expected_state;
2072 DXGI_SWAP_CHAIN_DESC swapchain_desc, result_desc;
2073 IDXGIOutput *output = NULL;
2074 IDXGISwapChain *swapchain;
2075 IDXGIFactory *factory;
2076 IDXGIAdapter *adapter;
2077 IDXGIDevice *device;
2078 unsigned int i;
2079 ULONG refcount;
2080 HRESULT hr;
2082 static const struct
2084 unsigned int width, height;
2086 sizes[] =
2088 {101, 101},
2089 {203, 204},
2090 {799, 601},
2093 if (!(device = create_device()))
2095 skip("Failed to create device.\n");
2096 return;
2099 hr = IDXGIDevice_GetAdapter(device, &adapter);
2100 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2102 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2103 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2105 swapchain_desc.BufferDesc.Width = 800;
2106 swapchain_desc.BufferDesc.Height = 600;
2107 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2108 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2109 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2110 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2111 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2112 swapchain_desc.SampleDesc.Count = 1;
2113 swapchain_desc.SampleDesc.Quality = 0;
2114 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2115 swapchain_desc.BufferCount = 1;
2116 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2117 swapchain_desc.Windowed = FALSE;
2118 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2119 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
2121 memset(&initial_state, 0, sizeof(initial_state));
2122 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
2124 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2125 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2126 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2127 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2128 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2129 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2130 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
2131 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2132 "GetContainingOutput failed, hr %#x.\n", hr);
2133 refcount = IDXGISwapChain_Release(swapchain);
2134 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2135 if (hr == DXGI_ERROR_UNSUPPORTED)
2137 win_skip("GetContainingOutput() not supported.\n");
2138 goto done;
2140 if (result_desc.Windowed)
2142 win_skip("Fullscreen not supported.\n");
2143 goto done;
2146 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
2148 for (i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i)
2150 /* Test CreateSwapChain(). */
2151 swapchain_desc.BufferDesc.Width = sizes[i].width;
2152 swapchain_desc.BufferDesc.Height = sizes[i].height;
2153 swapchain_desc.Windowed = FALSE;
2155 expected_state = initial_state;
2156 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2157 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect,
2158 sizes[i].width, sizes[i].height, output);
2160 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2161 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2163 check_swapchain_fullscreen_state(swapchain, &expected_state);
2164 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2165 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2166 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2167 result_desc.BufferDesc.Width, sizes[i].width);
2168 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2169 result_desc.BufferDesc.Height, sizes[i].height);
2171 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2172 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2173 check_swapchain_fullscreen_state(swapchain, &initial_state);
2175 refcount = IDXGISwapChain_Release(swapchain);
2176 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2178 /* Test SetFullscreenState(). */
2179 swapchain_desc.BufferDesc.Width = sizes[i].width;
2180 swapchain_desc.BufferDesc.Height = sizes[i].height;
2181 swapchain_desc.Windowed = TRUE;
2183 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2184 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2186 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2187 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2189 check_swapchain_fullscreen_state(swapchain, &expected_state);
2190 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2191 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2192 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2193 result_desc.BufferDesc.Width, sizes[i].width);
2194 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2195 result_desc.BufferDesc.Height, sizes[i].height);
2197 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2198 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2199 check_swapchain_fullscreen_state(swapchain, &initial_state);
2201 refcount = IDXGISwapChain_Release(swapchain);
2202 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2204 /* Test ResizeTarget(). */
2205 swapchain_desc.BufferDesc.Width = 800;
2206 swapchain_desc.BufferDesc.Height = 600;
2207 swapchain_desc.Windowed = TRUE;
2209 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2210 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2212 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2213 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2215 swapchain_desc.BufferDesc.Width = sizes[i].width;
2216 swapchain_desc.BufferDesc.Height = sizes[i].height;
2217 hr = IDXGISwapChain_ResizeTarget(swapchain, &swapchain_desc.BufferDesc);
2218 ok(SUCCEEDED(hr), "ResizeTarget failed, hr %#x.\n", hr);
2220 check_swapchain_fullscreen_state(swapchain, &expected_state);
2221 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2222 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2223 ok(result_desc.BufferDesc.Width == 800, "Got width %u.\n", result_desc.BufferDesc.Width);
2224 ok(result_desc.BufferDesc.Height == 600, "Got height %u.\n", result_desc.BufferDesc.Height);
2226 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2227 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2228 check_swapchain_fullscreen_state(swapchain, &initial_state);
2230 refcount = IDXGISwapChain_Release(swapchain);
2231 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2234 done:
2235 if (output)
2236 IDXGIOutput_Release(output);
2237 IDXGIAdapter_Release(adapter);
2238 refcount = IDXGIDevice_Release(device);
2239 ok(!refcount, "Device has %u references left.\n", refcount);
2240 refcount = IDXGIFactory_Release(factory);
2241 ok(!refcount, "Factory has %u references left.\n", refcount);
2244 static void test_create_factory(void)
2246 IDXGIFactory1 *factory;
2247 IUnknown *iface;
2248 HRESULT hr;
2250 iface = (void *)0xdeadbeef;
2251 hr = CreateDXGIFactory(&IID_IDXGIDevice, (void **)&iface);
2252 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2253 ok(!iface, "Got unexpected iface %p.\n", iface);
2255 hr = CreateDXGIFactory(&IID_IUnknown, (void **)&iface);
2256 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2257 IUnknown_Release(iface);
2259 hr = CreateDXGIFactory(&IID_IDXGIObject, (void **)&iface);
2260 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2261 IUnknown_Release(iface);
2263 factory = (void *)0xdeadbeef;
2264 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&iface);
2265 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2266 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
2267 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2268 ok(!factory, "Got unexpected factory %p.\n", factory);
2269 IUnknown_Release(iface);
2271 iface = (void *)0xdeadbeef;
2272 hr = CreateDXGIFactory(&IID_IDXGIFactory1, (void **)&iface);
2273 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2274 ok(!iface, "Got unexpected iface %p.\n", iface);
2276 if (!pCreateDXGIFactory1)
2278 win_skip("CreateDXGIFactory1 not available, skipping tests.\n");
2279 return;
2282 iface = (void *)0xdeadbeef;
2283 hr = pCreateDXGIFactory1(&IID_IDXGIDevice, (void **)&iface);
2284 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2285 ok(!iface, "Got unexpected iface %p.\n", iface);
2287 hr = pCreateDXGIFactory1(&IID_IUnknown, (void **)&iface);
2288 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2289 IUnknown_Release(iface);
2291 hr = pCreateDXGIFactory1(&IID_IDXGIObject, (void **)&iface);
2292 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2293 IUnknown_Release(iface);
2295 hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&iface);
2296 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2297 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
2298 ok(SUCCEEDED(hr), "Failed to query IDXGIFactory1 interface, hr %#x.\n", hr);
2299 IDXGIFactory1_Release(factory);
2300 IUnknown_Release(iface);
2302 hr = pCreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&iface);
2303 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr);
2304 IUnknown_Release(iface);
2307 static void test_private_data(void)
2309 ULONG refcount, expected_refcount;
2310 IDXGIDevice *device;
2311 HRESULT hr;
2312 IDXGIDevice *test_object;
2313 IUnknown *ptr;
2314 static const DWORD data[] = {1, 2, 3, 4};
2315 UINT size;
2316 static const GUID dxgi_private_data_test_guid =
2318 0xfdb37466,
2319 0x428f,
2320 0x4edf,
2321 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
2323 static const GUID dxgi_private_data_test_guid2 =
2325 0x2e5afac2,
2326 0x87b5,
2327 0x4c10,
2328 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
2331 if (!(device = create_device()))
2333 skip("Failed to create device, skipping tests.\n");
2334 return;
2337 test_object = create_device();
2339 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
2340 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
2341 * NULL interface is not considered a clear but as setting an interface pointer that
2342 * happens to be NULL. */
2343 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 0, NULL);
2344 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2345 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2346 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2347 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2348 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2349 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2350 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2352 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2353 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2354 size = sizeof(ptr) * 2;
2355 ptr = (IUnknown *)0xdeadbeef;
2356 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2357 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2358 ok(!ptr, "Got unexpected pointer %p.\n", ptr);
2359 ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size);
2361 refcount = get_refcount((IUnknown *)test_object);
2362 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2363 (IUnknown *)test_object);
2364 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2365 expected_refcount = refcount + 1;
2366 refcount = get_refcount((IUnknown *)test_object);
2367 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2368 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2369 (IUnknown *)test_object);
2370 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2371 refcount = get_refcount((IUnknown *)test_object);
2372 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2374 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2375 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2376 expected_refcount--;
2377 refcount = get_refcount((IUnknown *)test_object);
2378 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2380 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2381 (IUnknown *)test_object);
2382 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2383 size = sizeof(data);
2384 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, size, data);
2385 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2386 refcount = get_refcount((IUnknown *)test_object);
2387 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2388 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2389 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2390 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2391 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2393 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2394 (IUnknown *)test_object);
2395 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2396 expected_refcount++;
2397 size = 2 * sizeof(ptr);
2398 ptr = NULL;
2399 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2400 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2401 ok(size == sizeof(test_object), "Got unexpected size %u.\n", size);
2402 expected_refcount++;
2403 refcount = get_refcount((IUnknown *)test_object);
2404 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2405 if (ptr)
2406 IUnknown_Release(ptr);
2407 expected_refcount--;
2409 ptr = (IUnknown *)0xdeadbeef;
2410 size = 1;
2411 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2412 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2413 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2414 size = 2 * sizeof(ptr);
2415 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2416 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2417 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2418 refcount = get_refcount((IUnknown *)test_object);
2419 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2421 size = 1;
2422 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2423 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
2424 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2425 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2426 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, NULL, NULL);
2427 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2428 size = 0xdeadbabe;
2429 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, &size, &ptr);
2430 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
2431 ok(size == 0, "Got unexpected size %u.\n", size);
2432 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2433 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, NULL, &ptr);
2434 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2435 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2437 refcount = IDXGIDevice_Release(device);
2438 ok(!refcount, "Device has %u references left.\n", refcount);
2439 refcount = IDXGIDevice_Release(test_object);
2440 ok(!refcount, "Test object has %u references left.\n", refcount);
2443 static void test_swapchain_resize(void)
2445 DXGI_SWAP_CHAIN_DESC swapchain_desc;
2446 D3D10_TEXTURE2D_DESC texture_desc;
2447 DXGI_SURFACE_DESC surface_desc;
2448 IDXGISwapChain *swapchain;
2449 ID3D10Texture2D *texture;
2450 IDXGISurface *surface;
2451 IDXGIAdapter *adapter;
2452 IDXGIFactory *factory;
2453 IDXGIDevice *device;
2454 RECT client_rect, r;
2455 ULONG refcount;
2456 HWND window;
2457 HRESULT hr;
2458 BOOL ret;
2460 if (!(device = create_device()))
2462 skip("Failed to create device, skipping tests.\n");
2463 return;
2465 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2466 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2467 ret = GetClientRect(window, &client_rect);
2468 ok(ret, "Failed to get client rect.\n");
2470 hr = IDXGIDevice_GetAdapter(device, &adapter);
2471 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
2472 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2473 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
2474 IDXGIAdapter_Release(adapter);
2476 swapchain_desc.BufferDesc.Width = 640;
2477 swapchain_desc.BufferDesc.Height = 480;
2478 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2479 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2480 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2481 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2482 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2483 swapchain_desc.SampleDesc.Count = 1;
2484 swapchain_desc.SampleDesc.Quality = 0;
2485 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2486 swapchain_desc.BufferCount = 1;
2487 swapchain_desc.OutputWindow = window;
2488 swapchain_desc.Windowed = TRUE;
2489 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2490 swapchain_desc.Flags = 0;
2492 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2493 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
2494 IDXGIFactory_Release(factory);
2495 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2496 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2497 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2498 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2500 ret = GetClientRect(window, &r);
2501 ok(ret, "Failed to get client rect.\n");
2502 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2503 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2505 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2506 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2507 ok(swapchain_desc.BufferDesc.Width == 640,
2508 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2509 ok(swapchain_desc.BufferDesc.Height == 480,
2510 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2511 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2512 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2513 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2514 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2515 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2516 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2517 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2518 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2519 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2520 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2521 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2522 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2523 ok(swapchain_desc.SampleDesc.Count == 1,
2524 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2525 ok(!swapchain_desc.SampleDesc.Quality,
2526 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2527 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2528 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2529 ok(swapchain_desc.BufferCount == 1,
2530 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2531 ok(swapchain_desc.OutputWindow == window,
2532 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2533 ok(swapchain_desc.Windowed,
2534 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2535 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2536 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2537 ok(!swapchain_desc.Flags,
2538 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2540 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2541 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2542 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2543 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2544 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2545 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2546 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2548 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2549 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2550 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2551 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2552 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2553 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2554 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2555 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2556 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2557 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2558 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2559 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2561 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2562 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2564 ret = GetClientRect(window, &r);
2565 ok(ret, "Failed to get client rect.\n");
2566 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2567 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2569 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2570 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2571 ok(swapchain_desc.BufferDesc.Width == 640,
2572 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2573 ok(swapchain_desc.BufferDesc.Height == 480,
2574 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2575 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2576 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2577 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2578 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2579 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2580 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2581 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2582 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2583 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2584 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2585 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2586 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2587 ok(swapchain_desc.SampleDesc.Count == 1,
2588 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2589 ok(!swapchain_desc.SampleDesc.Quality,
2590 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2591 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2592 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2593 ok(swapchain_desc.BufferCount == 1,
2594 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2595 ok(swapchain_desc.OutputWindow == window,
2596 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2597 ok(swapchain_desc.Windowed,
2598 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2599 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2600 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2601 ok(!swapchain_desc.Flags,
2602 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2604 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2605 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2606 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2607 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2608 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2609 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2610 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2612 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2613 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2614 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2615 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2616 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2617 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2618 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2619 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2620 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2621 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2622 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2623 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2625 ID3D10Texture2D_Release(texture);
2626 IDXGISurface_Release(surface);
2627 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2628 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
2629 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2630 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2631 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2632 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2634 ret = GetClientRect(window, &r);
2635 ok(ret, "Failed to get client rect.\n");
2636 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2637 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2639 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2640 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2641 ok(swapchain_desc.BufferDesc.Width == 320,
2642 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2643 ok(swapchain_desc.BufferDesc.Height == 240,
2644 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2645 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2646 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2647 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2648 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2649 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2650 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2651 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
2652 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2653 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2654 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2655 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2656 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2657 ok(swapchain_desc.SampleDesc.Count == 1,
2658 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2659 ok(!swapchain_desc.SampleDesc.Quality,
2660 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2661 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2662 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2663 ok(swapchain_desc.BufferCount == 1,
2664 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2665 ok(swapchain_desc.OutputWindow == window,
2666 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2667 ok(swapchain_desc.Windowed,
2668 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2669 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2670 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2671 ok(!swapchain_desc.Flags,
2672 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2674 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2675 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2676 ok(surface_desc.Width == 320, "Got unexpected Width %u.\n", surface_desc.Width);
2677 ok(surface_desc.Height == 240, "Got unexpected Height %u.\n", surface_desc.Height);
2678 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", surface_desc.Format);
2679 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2680 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2682 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2683 ok(texture_desc.Width == 320, "Got unexpected Width %u.\n", texture_desc.Width);
2684 ok(texture_desc.Height == 240, "Got unexpected Height %u.\n", texture_desc.Height);
2685 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2686 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2687 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", texture_desc.Format);
2688 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2689 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2690 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2691 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2692 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2693 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2695 ID3D10Texture2D_Release(texture);
2696 IDXGISurface_Release(surface);
2698 hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
2699 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
2701 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2702 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2703 ok(swapchain_desc.BufferDesc.Width == client_rect.right - client_rect.left,
2704 "Got unexpected BufferDesc.Width %u, expected %u.\n",
2705 swapchain_desc.BufferDesc.Width, client_rect.right - client_rect.left);
2706 ok(swapchain_desc.BufferDesc.Height == client_rect.bottom - client_rect.top,
2707 "Got unexpected bufferDesc.Height %u, expected %u.\n",
2708 swapchain_desc.BufferDesc.Height, client_rect.bottom - client_rect.top);
2709 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2710 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2711 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2712 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2713 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2714 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2715 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
2716 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2717 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2718 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2719 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2720 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2721 ok(swapchain_desc.SampleDesc.Count == 1,
2722 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2723 ok(!swapchain_desc.SampleDesc.Quality,
2724 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2725 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2726 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2727 ok(swapchain_desc.BufferCount == 1,
2728 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2729 ok(swapchain_desc.OutputWindow == window,
2730 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2731 ok(swapchain_desc.Windowed,
2732 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2733 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2734 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2735 ok(!swapchain_desc.Flags,
2736 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2738 IDXGISwapChain_Release(swapchain);
2739 refcount = IDXGIDevice_Release(device);
2740 ok(!refcount, "Device has %u references left.\n", refcount);
2741 DestroyWindow(window);
2744 static void test_swapchain_parameters(void)
2746 IDXGISwapChain *swapchain;
2747 IUnknown *obj;
2748 IDXGIAdapter *adapter;
2749 IDXGIFactory *factory;
2750 IDXGIDevice *device;
2751 IDXGIResource *resource;
2752 DXGI_SWAP_CHAIN_DESC desc;
2753 HRESULT hr;
2754 unsigned int i, j;
2755 ULONG refcount;
2756 DXGI_USAGE usage, expected_usage, broken_usage;
2757 HWND window;
2758 static const struct
2760 BOOL windowed;
2761 UINT buffer_count;
2762 DXGI_SWAP_EFFECT swap_effect;
2763 HRESULT hr, vista_hr;
2764 UINT highest_accessible_buffer;
2766 tests[] =
2768 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2769 {TRUE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2770 {TRUE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2771 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2772 {TRUE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
2773 {TRUE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
2774 {TRUE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
2775 {TRUE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2776 {TRUE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2777 {TRUE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2778 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2779 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2780 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
2781 {TRUE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
2782 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2783 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2784 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2785 {TRUE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2786 {TRUE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2787 {TRUE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2788 {TRUE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2789 {TRUE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
2790 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
2791 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2792 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2793 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2794 {TRUE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2795 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2797 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2798 {FALSE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2799 {FALSE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2800 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2801 {FALSE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
2802 {FALSE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
2803 {FALSE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
2804 {FALSE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2805 {FALSE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2806 {FALSE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2807 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2808 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2809 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
2810 {FALSE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
2811 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2812 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2813 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2814 {FALSE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2815 {FALSE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2816 {FALSE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2817 {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2818 {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
2819 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
2820 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
2821 * process. Disable it for now.
2822 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2824 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2825 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2826 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2827 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2830 if (!(device = create_device()))
2832 skip("Failed to create device, skipping tests.\n");
2833 return;
2835 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2836 0, 0, 640, 480, 0, 0, 0, 0);
2838 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
2839 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown\n");
2841 hr = IDXGIDevice_GetAdapter(device, &adapter);
2842 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2844 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2845 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2847 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
2849 memset(&desc, 0, sizeof(desc));
2850 desc.BufferDesc.Width = registry_mode.dmPelsWidth;
2851 desc.BufferDesc.Height = registry_mode.dmPelsHeight;
2852 desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2853 desc.SampleDesc.Count = 1;
2854 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2855 desc.OutputWindow = window;
2857 desc.Windowed = tests[i].windowed;
2858 desc.BufferCount = tests[i].buffer_count;
2859 desc.SwapEffect = tests[i].swap_effect;
2861 hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
2862 ok(hr == tests[i].hr || broken(hr == tests[i].vista_hr)
2863 || (SUCCEEDED(tests[i].hr) && hr == DXGI_STATUS_OCCLUDED),
2864 "Got unexpected hr %#x, test %u.\n", hr, i);
2865 if (FAILED(hr))
2866 continue;
2868 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
2869 todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
2870 if (FAILED(hr))
2872 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2873 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2875 IDXGISwapChain_Release(swapchain);
2876 continue;
2879 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
2880 if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
2881 expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
2882 hr = IDXGIResource_GetUsage(resource, &usage);
2883 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
2884 ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
2886 IDXGIResource_Release(resource);
2888 hr = IDXGISwapChain_GetDesc(swapchain, &desc);
2889 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2891 for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
2893 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
2894 ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
2896 /* Buffers > 0 are supposed to be read only. This is the case except that in
2897 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
2898 * writable. This is not the case if an unsupported refresh rate is passed
2899 * for some reason, probably because the invalid refresh rate triggers a
2900 * kinda-sorta windowed mode.
2902 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
2903 * broken.
2905 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
2906 * the draw on the screen right away (Aero on or off doesn't matter), but
2907 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
2909 * Note that if the application doesn't have focused creating a fullscreen
2910 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
2911 * so use the Windowed property of the swapchain that was actually created. */
2912 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_READ_ONLY;
2913 broken_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
2915 if (desc.Windowed || j < tests[i].highest_accessible_buffer)
2916 broken_usage |= DXGI_USAGE_READ_ONLY;
2918 hr = IDXGIResource_GetUsage(resource, &usage);
2919 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr, i, j);
2920 ok(usage == expected_usage || broken(usage == broken_usage),
2921 "Got usage %x, expected %x, test %u, buffer %u.\n",
2922 usage, expected_usage, i, j);
2924 IDXGIResource_Release(resource);
2926 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
2927 ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
2929 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2930 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2932 IDXGISwapChain_Release(swapchain);
2935 IDXGIFactory_Release(factory);
2936 IDXGIAdapter_Release(adapter);
2937 IUnknown_Release(obj);
2938 refcount = IDXGIDevice_Release(device);
2939 ok(!refcount, "Device has %u references left.\n", refcount);
2940 DestroyWindow(window);
2943 static void test_maximum_frame_latency(void)
2945 IDXGIDevice1 *device1;
2946 IDXGIDevice *device;
2947 UINT max_latency;
2948 ULONG refcount;
2949 HRESULT hr;
2951 if (!(device = create_device()))
2953 skip("Failed to create device.\n");
2954 return;
2957 if (SUCCEEDED(IDXGIDevice_QueryInterface(device, &IID_IDXGIDevice1, (void **)&device1)))
2959 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
2960 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2961 ok(max_latency == DEFAULT_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
2963 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY);
2964 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2965 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
2966 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2967 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
2969 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY + 1);
2970 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2971 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
2972 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2973 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
2975 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, 0);
2976 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2977 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
2978 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2979 /* 0 does not reset to the default frame latency on all Windows versions. */
2980 ok(max_latency == DEFAULT_FRAME_LATENCY || broken(!max_latency),
2981 "Got unexpected maximum frame latency %u.\n", max_latency);
2983 IDXGIDevice1_Release(device1);
2985 else
2987 win_skip("IDXGIDevice1 is not implemented.\n");
2990 refcount = IDXGIDevice_Release(device);
2991 ok(!refcount, "Device has %u references left.\n", refcount);
2994 static void test_output_desc(void)
2996 IDXGIAdapter *adapter, *adapter2;
2997 IDXGIOutput *output, *output2;
2998 DXGI_OUTPUT_DESC desc;
2999 IDXGIFactory *factory;
3000 unsigned int i, j;
3001 ULONG refcount;
3002 HRESULT hr;
3004 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
3005 ok(SUCCEEDED(hr), "Failed to create DXGI factory, hr %#x.\n", hr);
3007 for (i = 0; ; ++i)
3009 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter);
3010 if (hr == DXGI_ERROR_NOT_FOUND)
3011 break;
3012 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3014 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter2);
3015 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3016 ok(adapter != adapter2, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter, adapter2);
3017 refcount = get_refcount((IUnknown *)adapter);
3018 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3019 IDXGIAdapter_Release(adapter2);
3021 refcount = get_refcount((IUnknown *)factory);
3022 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3023 refcount = get_refcount((IUnknown *)adapter);
3024 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3026 for (j = 0; ; ++j)
3028 MONITORINFOEXW monitor_info;
3029 BOOL ret;
3031 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output);
3032 if (hr == DXGI_ERROR_NOT_FOUND)
3033 break;
3034 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3036 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output2);
3037 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3038 ok(output != output2, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output, output2);
3039 refcount = get_refcount((IUnknown *)output);
3040 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3041 IDXGIOutput_Release(output2);
3043 refcount = get_refcount((IUnknown *)factory);
3044 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3045 refcount = get_refcount((IUnknown *)adapter);
3046 ok(refcount == 2, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3047 refcount = get_refcount((IUnknown *)output);
3048 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3050 hr = IDXGIOutput_GetDesc(output, NULL);
3051 ok(hr == E_INVALIDARG, "Got unexpected hr %#x for output %u on adapter %u.\n", hr, j, i);
3052 hr = IDXGIOutput_GetDesc(output, &desc);
3053 ok(SUCCEEDED(hr), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j, i, hr);
3055 monitor_info.cbSize = sizeof(monitor_info);
3056 ret = GetMonitorInfoW(desc.Monitor, (MONITORINFO *)&monitor_info);
3057 ok(ret, "Failed to get monitor info.\n");
3058 ok(!lstrcmpW(desc.DeviceName, monitor_info.szDevice), "Got unexpected device name %s, expected %s.\n",
3059 wine_dbgstr_w(desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
3060 ok(EqualRect(&desc.DesktopCoordinates, &monitor_info.rcMonitor),
3061 "Got unexpected desktop coordinates %s, expected %s.\n",
3062 wine_dbgstr_rect(&desc.DesktopCoordinates),
3063 wine_dbgstr_rect(&monitor_info.rcMonitor));
3065 IDXGIOutput_Release(output);
3066 refcount = get_refcount((IUnknown *)adapter);
3067 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3070 IDXGIAdapter_Release(adapter);
3071 refcount = get_refcount((IUnknown *)factory);
3072 ok(refcount == 1, "Get unexpected refcount %u.\n", refcount);
3075 refcount = IDXGIFactory_Release(factory);
3076 ok(!refcount, "IDXGIFactory has %u references left.\n", refcount);
3079 START_TEST(device)
3081 pCreateDXGIFactory1 = (void *)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
3083 registry_mode.dmSize = sizeof(registry_mode);
3084 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
3086 test_adapter_desc();
3087 test_check_interface_support();
3088 test_create_surface();
3089 test_parents();
3090 test_output();
3091 test_find_closest_matching_mode();
3092 test_create_swapchain();
3093 test_get_containing_output();
3094 test_set_fullscreen();
3095 test_default_fullscreen_target_output();
3096 test_resize_target();
3097 test_inexact_modes();
3098 test_create_factory();
3099 test_private_data();
3100 test_swapchain_resize();
3101 test_swapchain_parameters();
3102 test_maximum_frame_latency();
3103 test_output_desc();