comdlg32: Detach file dialog data after child windows were destroyed.
[wine.git] / dlls / dxgi / tests / device.c
blob8351a32e596d83d62cf2ff876c2a43df447dd7be
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 "dxgi1_6.h"
23 #include "d3d11.h"
24 #include "wine/test.h"
26 #ifndef ARRAY_SIZE
27 #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
28 #endif
30 enum frame_latency
32 DEFAULT_FRAME_LATENCY = 3,
33 MAX_FRAME_LATENCY = 16,
36 static DEVMODEW registry_mode;
38 static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
39 static HRESULT (WINAPI *pCreateDXGIFactory2)(UINT flags, REFIID iid, void **factory);
41 static ULONG get_refcount(IUnknown *iface)
43 IUnknown_AddRef(iface);
44 return IUnknown_Release(iface);
47 #define check_interface(a, b, c, d) check_interface_(__LINE__, a, b, c, d)
48 static HRESULT check_interface_(unsigned int line, void *iface, REFIID iid,
49 BOOL supported, BOOL is_broken)
51 HRESULT hr, expected_hr, broken_hr;
52 IUnknown *unknown = iface, *out;
54 if (supported)
56 expected_hr = S_OK;
57 broken_hr = E_NOINTERFACE;
59 else
61 expected_hr = E_NOINTERFACE;
62 broken_hr = S_OK;
65 out = (IUnknown *)0xdeadbeef;
66 hr = IUnknown_QueryInterface(unknown, iid, (void **)&out);
67 ok_(__FILE__, line)(hr == expected_hr || broken(is_broken && hr == broken_hr),
68 "Got hr %#x, expected %#x.\n", hr, expected_hr);
69 if (SUCCEEDED(hr))
70 IUnknown_Release(out);
71 else
72 ok_(__FILE__, line)(!out, "Got unexpected pointer %p.\n", out);
73 return hr;
76 #define MODE_DESC_IGNORE_RESOLUTION 0x00000001u
77 #define MODE_DESC_IGNORE_REFRESH_RATE 0x00000002u
78 #define MODE_DESC_IGNORE_FORMAT 0x00000004u
79 #define MODE_DESC_IGNORE_SCANLINE_ORDERING 0x00000008u
80 #define MODE_DESC_IGNORE_SCALING 0x00000010u
82 #define MODE_DESC_CHECK_RESOLUTION (~MODE_DESC_IGNORE_RESOLUTION)
83 #define MODE_DESC_CHECK_FORMAT (~MODE_DESC_IGNORE_FORMAT)
85 #define check_mode_desc(a, b, c) check_mode_desc_(__LINE__, a, b, c)
86 static void check_mode_desc_(unsigned int line, const DXGI_MODE_DESC *desc,
87 const DXGI_MODE_DESC *expected_desc, unsigned int ignore_flags)
89 if (!(ignore_flags & MODE_DESC_IGNORE_RESOLUTION))
91 ok_(__FILE__, line)(desc->Width == expected_desc->Width
92 && desc->Height == expected_desc->Height,
93 "Got resolution %ux%u, expected %ux%u.\n",
94 desc->Width, desc->Height, expected_desc->Width, expected_desc->Height);
96 if (!(ignore_flags & MODE_DESC_IGNORE_REFRESH_RATE))
98 ok_(__FILE__, line)(desc->RefreshRate.Numerator == expected_desc->RefreshRate.Numerator
99 && desc->RefreshRate.Denominator == expected_desc->RefreshRate.Denominator,
100 "Got refresh rate %u / %u, expected %u / %u.\n",
101 desc->RefreshRate.Numerator, desc->RefreshRate.Denominator,
102 expected_desc->RefreshRate.Denominator, expected_desc->RefreshRate.Denominator);
104 if (!(ignore_flags & MODE_DESC_IGNORE_FORMAT))
106 ok_(__FILE__, line)(desc->Format == expected_desc->Format,
107 "Got format %#x, expected %#x.\n", desc->Format, expected_desc->Format);
109 if (!(ignore_flags & MODE_DESC_IGNORE_SCANLINE_ORDERING))
111 ok_(__FILE__, line)(desc->ScanlineOrdering == expected_desc->ScanlineOrdering,
112 "Got scanline ordering %#x, expected %#x.\n",
113 desc->ScanlineOrdering, expected_desc->ScanlineOrdering);
115 if (!(ignore_flags & MODE_DESC_IGNORE_SCALING))
117 ok_(__FILE__, line)(desc->Scaling == expected_desc->Scaling,
118 "Got scaling %#x, expected %#x.\n",
119 desc->Scaling, expected_desc->Scaling);
123 static BOOL equal_luid(LUID a, LUID b)
125 return a.LowPart == b.LowPart && a.HighPart == b.HighPart;
128 #define check_adapter_desc(a, b) check_adapter_desc_(__LINE__, a, b)
129 static void check_adapter_desc_(unsigned int line, const DXGI_ADAPTER_DESC *desc,
130 const struct DXGI_ADAPTER_DESC *expected_desc)
132 ok_(__FILE__, line)(!lstrcmpW(desc->Description, expected_desc->Description),
133 "Got description %s, expected %s.\n",
134 wine_dbgstr_w(desc->Description), wine_dbgstr_w(expected_desc->Description));
135 ok_(__FILE__, line)(desc->VendorId == expected_desc->VendorId,
136 "Got vendor id %04x, expected %04x.\n",
137 desc->VendorId, expected_desc->VendorId);
138 ok_(__FILE__, line)(desc->DeviceId == expected_desc->DeviceId,
139 "Got device id %04x, expected %04x.\n",
140 desc->DeviceId, expected_desc->DeviceId);
141 ok_(__FILE__, line)(desc->SubSysId == expected_desc->SubSysId,
142 "Got subsys id %04x, expected %04x.\n",
143 desc->SubSysId, expected_desc->SubSysId);
144 ok_(__FILE__, line)(desc->Revision == expected_desc->Revision,
145 "Got revision %02x, expected %02x.\n",
146 desc->Revision, expected_desc->Revision);
147 ok_(__FILE__, line)(desc->DedicatedVideoMemory == expected_desc->DedicatedVideoMemory,
148 "Got dedicated video memory %lu, expected %lu.\n",
149 desc->DedicatedVideoMemory, expected_desc->DedicatedVideoMemory);
150 ok_(__FILE__, line)(desc->DedicatedSystemMemory == expected_desc->DedicatedSystemMemory,
151 "Got dedicated system memory %lu, expected %lu.\n",
152 desc->DedicatedSystemMemory, expected_desc->DedicatedSystemMemory);
153 ok_(__FILE__, line)(desc->SharedSystemMemory == expected_desc->SharedSystemMemory,
154 "Got shared system memory %lu, expected %lu.\n",
155 desc->SharedSystemMemory, expected_desc->SharedSystemMemory);
156 ok_(__FILE__, line)(equal_luid(desc->AdapterLuid, expected_desc->AdapterLuid),
157 "Got LUID %08x:%08x, expected %08x:%08x.\n",
158 desc->AdapterLuid.HighPart, desc->AdapterLuid.LowPart,
159 expected_desc->AdapterLuid.HighPart, expected_desc->AdapterLuid.LowPart);
162 #define check_output_desc(a, b) check_output_desc_(__LINE__, a, b)
163 static void check_output_desc_(unsigned int line, const DXGI_OUTPUT_DESC *desc,
164 const struct DXGI_OUTPUT_DESC *expected_desc)
166 ok_(__FILE__, line)(!lstrcmpW(desc->DeviceName, expected_desc->DeviceName),
167 "Got unexpected device name %s, expected %s.\n",
168 wine_dbgstr_w(desc->DeviceName), wine_dbgstr_w(expected_desc->DeviceName));
169 ok_(__FILE__, line)(EqualRect(&desc->DesktopCoordinates, &expected_desc->DesktopCoordinates),
170 "Got unexpected desktop coordinates %s, expected %s.\n",
171 wine_dbgstr_rect(&desc->DesktopCoordinates),
172 wine_dbgstr_rect(&expected_desc->DesktopCoordinates));
175 #define check_output_equal(a, b) check_output_equal_(__LINE__, a, b)
176 static void check_output_equal_(unsigned int line, IDXGIOutput *output1, IDXGIOutput *output2)
178 DXGI_OUTPUT_DESC desc1, desc2;
179 HRESULT hr;
181 hr = IDXGIOutput_GetDesc(output1, &desc1);
182 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
183 hr = IDXGIOutput_GetDesc(output2, &desc2);
184 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
185 check_output_desc_(line, &desc1, &desc2);
188 static BOOL output_belongs_to_adapter(IDXGIOutput *output, IDXGIAdapter *adapter)
190 DXGI_OUTPUT_DESC output_desc, desc;
191 unsigned int output_idx;
192 IDXGIOutput *o;
193 HRESULT hr;
195 hr = IDXGIOutput_GetDesc(output, &output_desc);
196 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
198 for (output_idx = 0; IDXGIAdapter_EnumOutputs(adapter, output_idx, &o) != DXGI_ERROR_NOT_FOUND; ++output_idx)
200 hr = IDXGIOutput_GetDesc(o, &desc);
201 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
202 IDXGIOutput_Release(o);
204 if (!lstrcmpW(desc.DeviceName, output_desc.DeviceName)
205 && EqualRect(&desc.DesktopCoordinates, &output_desc.DesktopCoordinates))
206 return TRUE;
209 return FALSE;
212 struct fullscreen_state
214 RECT window_rect;
215 RECT client_rect;
216 HMONITOR monitor;
217 RECT monitor_rect;
220 struct swapchain_fullscreen_state
222 struct fullscreen_state fullscreen_state;
223 BOOL fullscreen;
224 IDXGIOutput *target;
227 #define capture_fullscreen_state(a, b) capture_fullscreen_state_(__LINE__, a, b)
228 static void capture_fullscreen_state_(unsigned int line, struct fullscreen_state *state, HWND window)
230 MONITORINFOEXW monitor_info;
231 BOOL ret;
233 ret = GetWindowRect(window, &state->window_rect);
234 ok_(__FILE__, line)(ret, "GetWindowRect failed.\n");
235 ret = GetClientRect(window, &state->client_rect);
236 ok_(__FILE__, line)(ret, "GetClientRect failed.\n");
238 state->monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
239 ok_(__FILE__, line)(!!state->monitor, "Failed to get monitor from window.\n");
241 monitor_info.cbSize = sizeof(monitor_info);
242 ret = GetMonitorInfoW(state->monitor, (MONITORINFO *)&monitor_info);
243 ok_(__FILE__, line)(ret, "Failed to get monitor info.\n");
244 state->monitor_rect = monitor_info.rcMonitor;
247 #define check_fullscreen_state(a, b) check_fullscreen_state_(__LINE__, a, b)
248 static void check_fullscreen_state_(unsigned int line, const struct fullscreen_state *state,
249 const struct fullscreen_state *expected_state)
251 ok_(__FILE__, line)(EqualRect(&state->window_rect, &expected_state->window_rect),
252 "Got window rect %s, expected %s.\n",
253 wine_dbgstr_rect(&state->window_rect), wine_dbgstr_rect(&expected_state->window_rect));
254 ok_(__FILE__, line)(EqualRect(&state->client_rect, &expected_state->client_rect),
255 "Got client rect %s, expected %s.\n",
256 wine_dbgstr_rect(&state->client_rect), wine_dbgstr_rect(&expected_state->client_rect));
257 ok_(__FILE__, line)(state->monitor == expected_state->monitor,
258 "Got monitor %p, expected %p.\n",
259 state->monitor, expected_state->monitor);
260 ok_(__FILE__, line)(EqualRect(&state->monitor_rect, &expected_state->monitor_rect),
261 "Got monitor rect %s, expected %s.\n",
262 wine_dbgstr_rect(&state->monitor_rect), wine_dbgstr_rect(&expected_state->monitor_rect));
265 #define check_window_fullscreen_state(a, b) check_window_fullscreen_state_(__LINE__, a, b)
266 static void check_window_fullscreen_state_(unsigned int line, HWND window,
267 const struct fullscreen_state *expected_state)
269 struct fullscreen_state current_state;
270 capture_fullscreen_state_(line, &current_state, window);
271 check_fullscreen_state_(line, &current_state, expected_state);
274 #define check_swapchain_fullscreen_state(a, b) check_swapchain_fullscreen_state_(__LINE__, a, b)
275 static void check_swapchain_fullscreen_state_(unsigned int line, IDXGISwapChain *swapchain,
276 const struct swapchain_fullscreen_state *expected_state)
278 IDXGIOutput *containing_output, *target;
279 DXGI_SWAP_CHAIN_DESC swapchain_desc;
280 BOOL fullscreen;
281 HRESULT hr;
283 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
284 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
285 check_window_fullscreen_state_(line, swapchain_desc.OutputWindow, &expected_state->fullscreen_state);
287 ok_(__FILE__, line)(swapchain_desc.Windowed == !expected_state->fullscreen,
288 "Got windowed %#x, expected %#x.\n",
289 swapchain_desc.Windowed, !expected_state->fullscreen);
291 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
292 ok_(__FILE__, line)(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
293 ok_(__FILE__, line)(fullscreen == expected_state->fullscreen, "Got fullscreen %#x, expected %#x.\n",
294 fullscreen, expected_state->fullscreen);
296 if (!swapchain_desc.Windowed && expected_state->fullscreen)
298 IDXGIAdapter *adapter;
299 IDXGIDevice *device;
301 hr = IDXGISwapChain_GetDevice(swapchain, &IID_IDXGIDevice, (void **)&device);
302 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDevice failed, hr %#x.\n", hr);
303 hr = IDXGIDevice_GetAdapter(device, &adapter);
304 ok_(__FILE__, line)(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
305 IDXGIDevice_Release(device);
307 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
308 ok_(__FILE__, line)(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
310 check_output_equal_(line, target, expected_state->target);
311 ok_(__FILE__, line)(target == containing_output, "Got target %p, expected %p.\n",
312 target, containing_output);
313 ok_(__FILE__, line)(output_belongs_to_adapter(target, adapter),
314 "Output %p doesn't belong to adapter %p.\n",
315 target, adapter);
317 IDXGIOutput_Release(target);
318 IDXGIOutput_Release(containing_output);
319 IDXGIAdapter_Release(adapter);
321 else
323 ok_(__FILE__, line)(!target, "Got unexpected target %p.\n", target);
327 #define compute_expected_swapchain_fullscreen_state_after_fullscreen_change(a, b, c, d, e, f) \
328 compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(__LINE__, a, b, c, d, e, f)
329 static void compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(unsigned int line,
330 struct swapchain_fullscreen_state *state, const DXGI_SWAP_CHAIN_DESC *swapchain_desc,
331 const RECT *old_monitor_rect, unsigned int new_width, unsigned int new_height, IDXGIOutput *target)
333 if (!new_width && !new_height)
335 RECT client_rect;
336 GetClientRect(swapchain_desc->OutputWindow, &client_rect);
337 new_width = client_rect.right - client_rect.left;
338 new_height = client_rect.bottom - client_rect.top;
341 if (target)
343 DXGI_MODE_DESC mode_desc = swapchain_desc->BufferDesc;
344 HRESULT hr;
346 mode_desc.Width = new_width;
347 mode_desc.Height = new_height;
348 hr = IDXGIOutput_FindClosestMatchingMode(target, &mode_desc, &mode_desc, NULL);
349 ok_(__FILE__, line)(SUCCEEDED(hr), "FindClosestMatchingMode failed, hr %#x.\n", hr);
350 new_width = mode_desc.Width;
351 new_height = mode_desc.Height;
354 state->fullscreen = TRUE;
355 if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
357 unsigned int new_x = (old_monitor_rect->left >= 0)
358 ? old_monitor_rect->left : old_monitor_rect->right - new_width;
359 unsigned new_y = (old_monitor_rect->top >= 0)
360 ? old_monitor_rect->top : old_monitor_rect->bottom - new_height;
361 RECT new_monitor_rect = {0, 0, new_width, new_height};
362 OffsetRect(&new_monitor_rect, new_x, new_y);
364 SetRect(&state->fullscreen_state.client_rect, 0, 0, new_width, new_height);
365 state->fullscreen_state.monitor_rect = new_monitor_rect;
366 state->fullscreen_state.window_rect = new_monitor_rect;
368 if (target)
369 state->target = target;
371 else
373 state->fullscreen_state.window_rect = *old_monitor_rect;
374 SetRect(&state->fullscreen_state.client_rect, 0, 0,
375 old_monitor_rect->right - old_monitor_rect->left,
376 old_monitor_rect->bottom - old_monitor_rect->top);
380 static IDXGIDevice *create_device(UINT flags)
382 IDXGIDevice *dxgi_device;
383 ID3D10Device1 *device;
384 HRESULT hr;
386 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
387 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
388 goto success;
389 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
390 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
391 goto success;
392 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
393 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
394 goto success;
396 return NULL;
398 success:
399 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
400 ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice\n");
401 ID3D10Device1_Release(device);
403 return dxgi_device;
406 static void test_adapter_desc(void)
408 DXGI_ADAPTER_DESC1 desc1;
409 IDXGIAdapter1 *adapter1;
410 DXGI_ADAPTER_DESC desc;
411 IDXGIAdapter *adapter;
412 IDXGIDevice *device;
413 ULONG refcount;
414 HRESULT hr;
416 if (!(device = create_device(0)))
418 skip("Failed to create device, skipping tests.\n");
419 return;
422 hr = IDXGIDevice_GetAdapter(device, &adapter);
423 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
425 hr = IDXGIAdapter_GetDesc(adapter, NULL);
426 ok(hr == E_INVALIDARG, "GetDesc returned %#x, expected %#x.\n",
427 hr, E_INVALIDARG);
429 hr = IDXGIAdapter_GetDesc(adapter, &desc);
430 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
432 trace("%s.\n", wine_dbgstr_w(desc.Description));
433 trace("%04x: %04x:%04x (rev %02x).\n",
434 desc.SubSysId, desc.VendorId, desc.DeviceId, desc.Revision);
435 trace("Dedicated video memory: %lu (%lu MB).\n",
436 desc.DedicatedVideoMemory, desc.DedicatedVideoMemory / (1024 * 1024));
437 trace("Dedicated system memory: %lu (%lu MB).\n",
438 desc.DedicatedSystemMemory, desc.DedicatedSystemMemory / (1024 * 1024));
439 trace("Shared system memory: %lu (%lu MB).\n",
440 desc.SharedSystemMemory, desc.SharedSystemMemory / (1024 * 1024));
441 trace("LUID: %08x:%08x.\n", desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart);
443 hr = IDXGIAdapter_QueryInterface(adapter, &IID_IDXGIAdapter1, (void **)&adapter1);
444 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE), "Got unexpected hr %#x.\n", hr);
445 if (hr == E_NOINTERFACE)
446 goto done;
448 hr = IDXGIAdapter1_GetDesc1(adapter1, &desc1);
449 ok(SUCCEEDED(hr), "GetDesc1 failed, hr %#x.\n", hr);
451 ok(!lstrcmpW(desc.Description, desc1.Description),
452 "Got unexpected description %s.\n", wine_dbgstr_w(desc1.Description));
453 ok(desc1.VendorId == desc.VendorId, "Got unexpected vendor ID %04x.\n", desc1.VendorId);
454 ok(desc1.DeviceId == desc.DeviceId, "Got unexpected device ID %04x.\n", desc1.DeviceId);
455 ok(desc1.SubSysId == desc.SubSysId, "Got unexpected sub system ID %04x.\n", desc1.SubSysId);
456 ok(desc1.Revision == desc.Revision, "Got unexpected revision %02x.\n", desc1.Revision);
457 ok(desc1.DedicatedVideoMemory == desc.DedicatedVideoMemory,
458 "Got unexpected dedicated video memory %lu.\n", desc1.DedicatedVideoMemory);
459 ok(desc1.DedicatedSystemMemory == desc.DedicatedSystemMemory,
460 "Got unexpected dedicated system memory %lu.\n", desc1.DedicatedSystemMemory);
461 ok(desc1.SharedSystemMemory == desc.SharedSystemMemory,
462 "Got unexpected shared system memory %lu.\n", desc1.SharedSystemMemory);
463 ok(equal_luid(desc1.AdapterLuid, desc.AdapterLuid),
464 "Got unexpected adapter LUID %08x:%08x.\n", desc1.AdapterLuid.HighPart, desc1.AdapterLuid.LowPart);
465 trace("Flags: %08x.\n", desc1.Flags);
467 IDXGIAdapter1_Release(adapter1);
469 done:
470 IDXGIAdapter_Release(adapter);
471 refcount = IDXGIDevice_Release(device);
472 ok(!refcount, "Device has %u references left.\n", refcount);
475 static void test_adapter_luid(void)
477 DXGI_ADAPTER_DESC device_adapter_desc, desc, desc2;
478 static const LUID luid = {0xdeadbeef, 0xdeadbeef};
479 IDXGIAdapter *adapter, *adapter2;
480 unsigned int found_adapter_count;
481 unsigned int adapter_index;
482 BOOL is_null_luid_adapter;
483 IDXGIFactory4 *factory4;
484 IDXGIFactory *factory;
485 BOOL have_unique_luid;
486 IDXGIDevice *device;
487 ULONG refcount;
488 HRESULT hr;
490 if (!(device = create_device(0)))
492 skip("Failed to create device.\n");
493 return;
496 hr = IDXGIDevice_GetAdapter(device, &adapter);
497 ok(hr == S_OK, "Failed to get adapter, hr %#x.\n", hr);
498 hr = IDXGIAdapter_GetDesc(adapter, &device_adapter_desc);
499 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
500 IDXGIAdapter_Release(adapter);
501 refcount = IDXGIDevice_Release(device);
502 ok(!refcount, "Device has %u references left.\n", refcount);
504 is_null_luid_adapter = !device_adapter_desc.AdapterLuid.HighPart
505 && !device_adapter_desc.AdapterLuid.LowPart;
507 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
508 ok(hr == S_OK, "Failed to create DXGI factory, hr %#x.\n", hr);
510 hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory4, (void **)&factory4);
511 ok(hr == S_OK || hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
513 have_unique_luid = TRUE;
514 found_adapter_count = 0;
515 adapter_index = 0;
516 while ((hr = IDXGIFactory_EnumAdapters(factory, adapter_index, &adapter)) == S_OK)
518 hr = IDXGIAdapter_GetDesc(adapter, &desc);
519 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
521 if (equal_luid(desc.AdapterLuid, device_adapter_desc.AdapterLuid))
523 check_adapter_desc(&desc, &device_adapter_desc);
524 ++found_adapter_count;
527 if (equal_luid(desc.AdapterLuid, luid))
528 have_unique_luid = FALSE;
530 if (factory4)
532 hr = IDXGIFactory4_EnumAdapterByLuid(factory4, desc.AdapterLuid,
533 &IID_IDXGIAdapter, (void **)&adapter2);
534 ok(hr == S_OK, "Failed to enum adapter by LUID, hr %#x.\n", hr);
535 hr = IDXGIAdapter_GetDesc(adapter2, &desc2);
536 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
537 check_adapter_desc(&desc2, &desc);
538 ok(adapter2 != adapter, "Expected to get new instance of IDXGIAdapter.\n");
539 refcount = IDXGIAdapter_Release(adapter2);
540 ok(!refcount, "Adapter has %u references left.\n", refcount);
543 refcount = IDXGIAdapter_Release(adapter);
544 ok(!refcount, "Adapter has %u references left.\n", refcount);
546 ++adapter_index;
548 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
550 /* Older versions of WARP aren't enumerated by IDXGIFactory_EnumAdapters(). */
551 todo_wine ok(found_adapter_count == 1 || broken(is_null_luid_adapter),
552 "Found %u adapters for LUID %08x:%08x.\n",
553 found_adapter_count, device_adapter_desc.AdapterLuid.HighPart,
554 device_adapter_desc.AdapterLuid.LowPart);
556 if (factory4)
557 IDXGIFactory4_Release(factory4);
558 refcount = IDXGIFactory_Release(factory);
559 ok(!refcount, "Factory has %u references left.\n", refcount);
561 if (!pCreateDXGIFactory2
562 || FAILED(hr = pCreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory4)))
564 skip("DXGI 1.4 is not available.\n");
565 return;
568 hr = IDXGIFactory4_EnumAdapterByLuid(factory4, device_adapter_desc.AdapterLuid,
569 &IID_IDXGIAdapter, (void **)&adapter);
570 todo_wine ok(hr == S_OK, "Failed to enum adapter by LUID, hr %#x.\n", hr);
571 if (SUCCEEDED(hr))
573 hr = IDXGIAdapter_GetDesc(adapter, &desc);
574 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
575 check_adapter_desc(&desc, &device_adapter_desc);
576 refcount = IDXGIAdapter_Release(adapter);
577 ok(!refcount, "Adapter has %u references left.\n", refcount);
580 if (have_unique_luid)
582 hr = IDXGIFactory4_EnumAdapterByLuid(factory4, luid, &IID_IDXGIAdapter, (void **)&adapter);
583 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
585 else
587 skip("Our LUID is not unique.\n");
590 refcount = IDXGIFactory4_Release(factory4);
591 ok(!refcount, "Factory has %u references left.\n", refcount);
594 static void test_check_interface_support(void)
596 LARGE_INTEGER driver_version;
597 IDXGIAdapter *adapter;
598 IDXGIDevice *device;
599 IUnknown *iface;
600 ULONG refcount;
601 HRESULT hr;
603 if (!(device = create_device(0)))
605 skip("Failed to create device.\n");
606 return;
609 hr = IDXGIDevice_GetAdapter(device, &adapter);
610 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
612 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, NULL);
613 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
614 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, &driver_version);
615 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
617 trace("UMD version: %u.%u.%u.%u.\n",
618 HIWORD(U(driver_version).HighPart), LOWORD(U(driver_version).HighPart),
619 HIWORD(U(driver_version).LowPart), LOWORD(U(driver_version).LowPart));
621 hr = IDXGIDevice_QueryInterface(device, &IID_ID3D10Device1, (void **)&iface);
622 if (SUCCEEDED(hr))
624 IUnknown_Release(iface);
625 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, NULL);
626 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
627 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, &driver_version);
628 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
630 else
632 win_skip("D3D10.1 is not supported.\n");
635 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, NULL);
636 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
637 driver_version.HighPart = driver_version.LowPart = 0xdeadbeef;
638 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, &driver_version);
639 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
640 ok(driver_version.HighPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.HighPart);
641 ok(driver_version.LowPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.LowPart);
643 IDXGIAdapter_Release(adapter);
644 refcount = IDXGIDevice_Release(device);
645 ok(!refcount, "Device has %u references left.\n", refcount);
648 static void test_create_surface(void)
650 DXGI_SURFACE_DESC desc;
651 IDXGISurface *surface;
652 IDXGIDevice *device;
653 ULONG refcount;
654 HRESULT hr;
656 if (!(device = create_device(0)))
658 skip("Failed to create device, skipping tests.\n");
659 return;
662 desc.Width = 512;
663 desc.Height = 512;
664 desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
665 desc.SampleDesc.Count = 1;
666 desc.SampleDesc.Quality = 0;
668 hr = IDXGIDevice_CreateSurface(device, &desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
669 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
671 check_interface(surface, &IID_ID3D10Texture2D, TRUE, FALSE);
672 /* Not available on all Windows versions. */
673 check_interface(surface, &IID_ID3D11Texture2D, TRUE, TRUE);
674 /* Not available on all Windows versions. */
675 check_interface(surface, &IID_IDXGISurface1, TRUE, TRUE);
677 IDXGISurface_Release(surface);
678 refcount = IDXGIDevice_Release(device);
679 ok(!refcount, "Device has %u references left.\n", refcount);
682 static void test_parents(void)
684 DXGI_SURFACE_DESC surface_desc;
685 IDXGISurface *surface;
686 IDXGIFactory *factory;
687 IDXGIAdapter *adapter;
688 IDXGIDevice *device;
689 IDXGIOutput *output;
690 IUnknown *parent;
691 ULONG refcount;
692 HRESULT hr;
694 if (!(device = create_device(0)))
696 skip("Failed to create device, skipping tests.\n");
697 return;
700 surface_desc.Width = 512;
701 surface_desc.Height = 512;
702 surface_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
703 surface_desc.SampleDesc.Count = 1;
704 surface_desc.SampleDesc.Quality = 0;
706 hr = IDXGIDevice_CreateSurface(device, &surface_desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
707 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
709 hr = IDXGISurface_GetParent(surface, &IID_IDXGIDevice, (void **)&parent);
710 IDXGISurface_Release(surface);
711 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
712 ok(parent == (IUnknown *)device, "Got parent %p, expected %p.\n", parent, device);
713 IUnknown_Release(parent);
715 hr = IDXGIDevice_GetAdapter(device, &adapter);
716 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
718 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
719 if (hr == DXGI_ERROR_NOT_FOUND)
721 skip("Adapter has not outputs, skipping output tests.\n");
723 else
725 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
727 hr = IDXGIOutput_GetParent(output, &IID_IDXGIAdapter, (void **)&parent);
728 IDXGIOutput_Release(output);
729 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
730 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
731 IUnknown_Release(parent);
734 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
735 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
737 hr = IDXGIFactory_GetParent(factory, &IID_IUnknown, (void **)&parent);
738 ok(hr == E_NOINTERFACE, "GetParent returned %#x, expected %#x.\n", hr, E_NOINTERFACE);
739 ok(parent == NULL, "Got parent %p, expected %p.\n", parent, NULL);
740 IDXGIFactory_Release(factory);
742 hr = IDXGIDevice_GetParent(device, &IID_IDXGIAdapter, (void **)&parent);
743 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
744 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
745 IUnknown_Release(parent);
747 IDXGIAdapter_Release(adapter);
748 refcount = IDXGIDevice_Release(device);
749 ok(!refcount, "Device has %u references left.\n", refcount);
752 static void test_output(void)
754 IDXGIAdapter *adapter;
755 IDXGIDevice *device;
756 HRESULT hr;
757 IDXGIOutput *output;
758 ULONG refcount;
759 UINT mode_count, mode_count_comp, i;
760 DXGI_MODE_DESC *modes;
762 if (!(device = create_device(0)))
764 skip("Failed to create device, skipping tests.\n");
765 return;
768 hr = IDXGIDevice_GetAdapter(device, &adapter);
769 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
771 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
772 if (hr == DXGI_ERROR_NOT_FOUND)
774 skip("Adapter doesn't have any outputs, skipping tests.\n");
775 IDXGIAdapter_Release(adapter);
776 IDXGIDevice_Release(device);
777 return;
779 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
781 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NULL, NULL);
782 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
784 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
785 ok(SUCCEEDED(hr)
786 || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Remote Desktop Services / Win 7 testbot */
787 "Failed to list modes, hr %#x.\n", hr);
788 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
790 win_skip("GetDisplayModeList() not supported.\n");
791 IDXGIOutput_Release(output);
792 IDXGIAdapter_Release(adapter);
793 IDXGIDevice_Release(device);
794 return;
796 mode_count_comp = mode_count;
798 hr = IDXGIOutput_GetDisplayModeList(output, 0, 0, &mode_count, NULL);
799 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
800 ok(!mode_count, "Got unexpected mode_count %u.\n", mode_count);
802 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
803 DXGI_ENUM_MODES_SCALING, &mode_count, NULL);
804 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
805 ok(mode_count >= mode_count_comp, "Got unexpected mode_count %u, expected >= %u.\n", mode_count, mode_count_comp);
806 mode_count_comp = mode_count;
808 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * (mode_count + 10));
810 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
811 DXGI_ENUM_MODES_SCALING, NULL, modes);
812 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
813 ok(!modes[0].Height, "No output was expected.\n");
815 mode_count = 0;
816 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
817 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
818 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
819 ok(!modes[0].Height, "No output was expected.\n");
821 mode_count = mode_count_comp;
822 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
823 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
824 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
825 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
827 for (i = 0; i < mode_count; i++)
829 ok(modes[i].Height && modes[i].Width, "Proper mode was expected\n");
832 mode_count += 5;
833 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
834 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
835 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
836 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
838 if (mode_count_comp)
840 mode_count = mode_count_comp - 1;
841 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
842 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
843 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
844 ok(mode_count == mode_count_comp - 1, "Got unexpected mode_count %u, expected %u.\n",
845 mode_count, mode_count_comp - 1);
847 else
849 skip("Not enough modes for test, skipping.\n");
852 HeapFree(GetProcessHeap(), 0, modes);
853 IDXGIOutput_Release(output);
854 IDXGIAdapter_Release(adapter);
855 refcount = IDXGIDevice_Release(device);
856 ok(!refcount, "Device has %u references left.\n", refcount);
859 static void test_find_closest_matching_mode(void)
861 DXGI_MODE_DESC *modes, mode, matching_mode;
862 unsigned int i, mode_count;
863 IDXGIAdapter *adapter;
864 IDXGIDevice *device;
865 IDXGIOutput *output;
866 ULONG refcount;
867 HRESULT hr;
869 if (!(device = create_device(0)))
871 skip("Failed to create device.\n");
872 return;
875 hr = IDXGIDevice_GetAdapter(device, &adapter);
876 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
878 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
879 if (hr == DXGI_ERROR_NOT_FOUND)
881 win_skip("Adapter doesn't have any outputs.\n");
882 IDXGIAdapter_Release(adapter);
883 IDXGIDevice_Release(device);
884 return;
886 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
888 memset(&mode, 0, sizeof(mode));
889 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
890 ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
891 "Got unexpected hr %#x.\n", hr);
892 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
894 win_skip("FindClosestMatchingMode() not supported.\n");
895 goto done;
898 memset(&mode, 0, sizeof(mode));
899 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, (IUnknown *)device);
900 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
902 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
903 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
905 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
907 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
908 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
910 for (i = 0; i < mode_count; ++i)
912 mode = modes[i];
913 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
914 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
915 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING);
917 mode.Format = DXGI_FORMAT_UNKNOWN;
918 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
919 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
921 mode = modes[i];
922 mode.Width = 0;
923 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
924 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
926 mode = modes[i];
927 mode.Height = 0;
928 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
929 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
931 mode = modes[i];
932 mode.Width = mode.Height = 0;
933 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
934 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
935 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_RESOLUTION);
936 ok(matching_mode.Width > 0 && matching_mode.Height > 0, "Got unexpected resolution %ux%u.\n",
937 matching_mode.Width, matching_mode.Height);
939 mode = modes[i];
940 mode.RefreshRate.Numerator = mode.RefreshRate.Denominator = 0;
941 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
942 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
943 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_REFRESH_RATE);
944 ok(matching_mode.RefreshRate.Numerator > 0 && matching_mode.RefreshRate.Denominator > 0,
945 "Got unexpected refresh rate %u / %u.\n",
946 matching_mode.RefreshRate.Numerator, matching_mode.RefreshRate.Denominator);
948 mode = modes[i];
949 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
950 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
951 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
952 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_SCANLINE_ORDERING);
953 ok(matching_mode.ScanlineOrdering, "Got unexpected scanline ordering %#x.\n",
954 matching_mode.ScanlineOrdering);
956 memset(&mode, 0, sizeof(mode));
957 mode.Width = modes[i].Width;
958 mode.Height = modes[i].Height;
959 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
960 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
961 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
962 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
964 memset(&mode, 0, sizeof(mode));
965 mode.Width = modes[i].Width - 1;
966 mode.Height = modes[i].Height - 1;
967 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
968 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
969 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
970 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
972 memset(&mode, 0, sizeof(mode));
973 mode.Width = modes[i].Width + 1;
974 mode.Height = modes[i].Height + 1;
975 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
976 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
977 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
978 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
981 memset(&mode, 0, sizeof(mode));
982 mode.Width = mode.Height = 10;
983 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
984 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
985 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
986 /* Find mode for the lowest resolution. */
987 mode = modes[0];
988 for (i = 0; i < mode_count; ++i)
990 if (mode.Width >= modes[i].Width && mode.Height >= modes[i].Height)
991 mode = modes[i];
993 check_mode_desc(&matching_mode, &mode, MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
995 memset(&mode, 0, sizeof(mode));
996 mode.Width = modes[0].Width;
997 mode.Height = modes[0].Height;
998 mode.Format = modes[0].Format;
999 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST;
1000 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
1001 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1002 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
1004 memset(&mode, 0, sizeof(mode));
1005 mode.Width = modes[0].Width;
1006 mode.Height = modes[0].Height;
1007 mode.Format = modes[0].Format;
1008 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST;
1009 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
1010 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1011 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
1013 memset(&mode, 0, sizeof(mode));
1014 mode.Width = modes[0].Width;
1015 mode.Height = modes[0].Height;
1016 mode.Format = modes[0].Format;
1017 mode.Scaling = DXGI_MODE_SCALING_CENTERED;
1018 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
1019 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1020 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
1022 memset(&mode, 0, sizeof(mode));
1023 mode.Width = modes[0].Width;
1024 mode.Height = modes[0].Height;
1025 mode.Format = modes[0].Format;
1026 mode.Scaling = DXGI_MODE_SCALING_STRETCHED;
1027 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
1028 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1029 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
1031 HeapFree(GetProcessHeap(), 0, modes);
1033 done:
1034 IDXGIOutput_Release(output);
1035 IDXGIAdapter_Release(adapter);
1036 refcount = IDXGIDevice_Release(device);
1037 ok(!refcount, "Device has %u references left.\n", refcount);
1040 struct refresh_rates
1042 UINT numerator;
1043 UINT denominator;
1044 BOOL numerator_should_pass;
1045 BOOL denominator_should_pass;
1048 static void test_create_swapchain(void)
1050 struct swapchain_fullscreen_state initial_state, expected_state;
1051 unsigned int i, expected_width, expected_height;
1052 DXGI_SWAP_CHAIN_DESC creation_desc, result_desc;
1053 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
1054 DXGI_SWAP_CHAIN_DESC1 swapchain_desc;
1055 IDXGIDevice *device, *bgra_device;
1056 ULONG refcount, expected_refcount;
1057 IUnknown *obj, *obj2, *parent;
1058 IDXGISwapChain1 *swapchain1;
1059 RECT *expected_client_rect;
1060 IDXGISwapChain *swapchain;
1061 IDXGISurface1 *surface;
1062 IDXGIAdapter *adapter;
1063 IDXGIFactory *factory;
1064 IDXGIOutput *target;
1065 BOOL fullscreen;
1066 HWND window;
1067 HRESULT hr;
1069 const struct refresh_rates refresh_list[] =
1071 {60, 60, FALSE, FALSE},
1072 {60, 0, TRUE, FALSE},
1073 {60, 1, TRUE, TRUE},
1074 { 0, 60, TRUE, FALSE},
1075 { 0, 0, TRUE, FALSE},
1078 if (!(device = create_device(0)))
1080 skip("Failed to create device, skipping tests.\n");
1081 return;
1084 creation_desc.BufferDesc.Width = 800;
1085 creation_desc.BufferDesc.Height = 600;
1086 creation_desc.BufferDesc.RefreshRate.Numerator = 60;
1087 creation_desc.BufferDesc.RefreshRate.Denominator = 60;
1088 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1089 creation_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1090 creation_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1091 creation_desc.SampleDesc.Count = 1;
1092 creation_desc.SampleDesc.Quality = 0;
1093 creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1094 creation_desc.BufferCount = 1;
1095 creation_desc.OutputWindow = NULL;
1096 creation_desc.Windowed = TRUE;
1097 creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1098 creation_desc.Flags = 0;
1100 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
1101 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
1103 hr = IDXGIDevice_GetAdapter(device, &adapter);
1104 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1106 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1107 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1109 expected_refcount = get_refcount((IUnknown *)adapter);
1110 refcount = get_refcount((IUnknown *)factory);
1111 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
1112 refcount = get_refcount((IUnknown *)device);
1113 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
1115 creation_desc.OutputWindow = NULL;
1116 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1117 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1119 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1120 memset(&initial_state, 0, sizeof(initial_state));
1121 capture_fullscreen_state(&initial_state.fullscreen_state, creation_desc.OutputWindow);
1123 hr = IDXGIFactory_CreateSwapChain(factory, NULL, &creation_desc, &swapchain);
1124 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1125 hr = IDXGIFactory_CreateSwapChain(factory, obj, NULL, &swapchain);
1126 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1127 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, NULL);
1128 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1129 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1130 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
1132 refcount = get_refcount((IUnknown *)adapter);
1133 ok(refcount >= expected_refcount, "Got refcount %u, expected >= %u.\n", refcount, expected_refcount);
1134 refcount = get_refcount((IUnknown *)factory);
1135 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
1136 refcount = get_refcount((IUnknown *)device);
1137 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
1139 hr = IDXGISwapChain_GetDesc(swapchain, NULL);
1140 ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr);
1142 hr = IDXGISwapChain_GetParent(swapchain, &IID_IUnknown, (void **)&parent);
1143 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
1144 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
1145 refcount = IUnknown_Release(parent);
1146 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
1148 hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent);
1149 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
1150 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
1151 refcount = IUnknown_Release(parent);
1152 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
1154 hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain1, (void **)&swapchain1);
1155 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
1156 "Failed to query IDXGISwapChain1 interface, hr %#x.\n", hr);
1157 if (SUCCEEDED(hr))
1159 hr = IDXGISwapChain1_GetDesc1(swapchain1, NULL);
1160 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
1161 hr = IDXGISwapChain1_GetDesc1(swapchain1, &swapchain_desc);
1162 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1163 ok(!swapchain_desc.Stereo, "Got unexpected stereo %#x.\n", swapchain_desc.Stereo);
1164 ok(swapchain_desc.Scaling == DXGI_SCALING_STRETCH,
1165 "Got unexpected scaling %#x.\n", swapchain_desc.Scaling);
1166 ok(swapchain_desc.AlphaMode == DXGI_ALPHA_MODE_IGNORE,
1167 "Got unexpected alpha mode %#x.\n", swapchain_desc.AlphaMode);
1168 hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, NULL);
1169 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
1170 hr = IDXGISwapChain1_GetFullscreenDesc(swapchain1, &fullscreen_desc);
1171 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1172 ok(fullscreen_desc.Windowed == creation_desc.Windowed,
1173 "Got unexpected windowed %#x.\n", fullscreen_desc.Windowed);
1174 hr = IDXGISwapChain1_GetHwnd(swapchain1, &window);
1175 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1176 ok(window == creation_desc.OutputWindow, "Got unexpected window %p.\n", window);
1177 IDXGISwapChain1_Release(swapchain1);
1180 refcount = IDXGISwapChain_Release(swapchain);
1181 ok(!refcount, "Swapchain has %u references left.\n", refcount);
1183 refcount = get_refcount((IUnknown *)factory);
1184 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
1186 for (i = 0; i < ARRAY_SIZE(refresh_list); ++i)
1188 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
1189 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
1191 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1192 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
1194 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1195 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
1197 ok(result_desc.Windowed == creation_desc.Windowed, "Test %u: Got unexpected windowed %#x.\n",
1198 i, result_desc.Windowed);
1200 todo_wine_if (!refresh_list[i].numerator_should_pass)
1201 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
1202 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
1204 todo_wine_if (!refresh_list[i].denominator_should_pass)
1205 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
1206 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
1208 fullscreen = 0xdeadbeef;
1209 target = (void *)0xdeadbeef;
1210 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1211 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1212 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1213 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1215 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
1216 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1217 fullscreen = 0xdeadbeef;
1218 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1219 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1220 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1221 target = (void *)0xdeadbeef;
1222 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1223 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1224 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1226 check_swapchain_fullscreen_state(swapchain, &initial_state);
1227 IDXGISwapChain_Release(swapchain);
1230 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1232 /* Test GDI-compatible swapchain */
1233 bgra_device = create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT);
1234 ok(!!bgra_device, "Failed to create BGRA capable device.\n");
1236 hr = IDXGIDevice_QueryInterface(bgra_device, &IID_IUnknown, (void **)&obj2);
1237 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
1239 hr = IDXGIFactory_CreateSwapChain(factory, obj2, &creation_desc, &swapchain);
1240 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1242 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface1, (void **)&surface);
1243 if (SUCCEEDED(hr))
1245 HDC hdc;
1247 hr = IDXGISurface1_GetDC(surface, FALSE, &hdc);
1248 ok(FAILED(hr), "Expected GetDC() to fail, %#x\n", hr);
1250 IDXGISurface1_Release(surface);
1251 IDXGISwapChain_Release(swapchain);
1253 creation_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
1254 creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
1256 hr = IDXGIFactory_CreateSwapChain(factory, obj2, &creation_desc, &swapchain);
1257 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1259 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1260 creation_desc.Flags = 0;
1262 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface1, (void **)&surface);
1263 ok(SUCCEEDED(hr), "Failed to get front buffer, hr %#x.\n", hr);
1265 hr = IDXGISurface1_GetDC(surface, FALSE, &hdc);
1266 ok(SUCCEEDED(hr), "Expected GetDC() to succeed, %#x\n", hr);
1267 IDXGISurface1_ReleaseDC(surface, NULL);
1269 IDXGISurface1_Release(surface);
1270 IDXGISwapChain_Release(swapchain);
1272 else
1274 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1275 IDXGISwapChain_Release(swapchain);
1277 IUnknown_Release(obj2);
1278 IDXGIDevice_Release(bgra_device);
1280 creation_desc.Windowed = FALSE;
1282 for (i = 0; i < ARRAY_SIZE(refresh_list); ++i)
1284 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
1285 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
1287 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1288 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
1290 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1291 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
1293 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1294 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1295 if (result_desc.Windowed != creation_desc.Windowed)
1296 trace("Test %u: Failed to change fullscreen state.\n", i);
1298 todo_wine_if (!refresh_list[i].numerator_should_pass)
1299 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
1300 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
1302 todo_wine_if (!refresh_list[i].denominator_should_pass)
1303 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
1304 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
1306 fullscreen = FALSE;
1307 target = NULL;
1308 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1309 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1310 ok(fullscreen == !result_desc.Windowed, "Test %u: Got fullscreen %#x, expected %#x.\n",
1311 i, fullscreen, result_desc.Windowed);
1312 ok(result_desc.Windowed ? !target : !!target, "Test %u: Got unexpected target %p.\n", i, target);
1313 if (!result_desc.Windowed)
1315 IDXGIOutput *containing_output;
1316 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1317 ok(SUCCEEDED(hr), "Test %u: GetContainingOutput failed, hr %#x.\n", i, hr);
1318 ok(containing_output == target, "Test %u: Got unexpected containing output pointer %p.\n",
1319 i, containing_output);
1320 IDXGIOutput_Release(containing_output);
1322 ok(output_belongs_to_adapter(target, adapter),
1323 "Test %u: Output %p doesn't belong to adapter %p.\n",
1324 i, target, adapter);
1325 IDXGIOutput_Release(target);
1327 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
1328 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1329 fullscreen = FALSE;
1330 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1331 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1332 ok(fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1333 target = NULL;
1334 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1335 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1336 ok(!!target, "Test %u: Got unexpected target %p.\n", i, target);
1337 IDXGIOutput_Release(target);
1340 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1341 ok(SUCCEEDED(hr), "Test %u: SetFullscreenState failed, hr %#x.\n", i, hr);
1343 fullscreen = 0xdeadbeef;
1344 target = (void *)0xdeadbeef;
1345 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1346 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1347 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1348 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1350 check_swapchain_fullscreen_state(swapchain, &initial_state);
1351 IDXGISwapChain_Release(swapchain);
1354 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1356 /* Test swapchain creation with backbuffer width and height equal to 0. */
1357 expected_state = initial_state;
1358 expected_client_rect = &expected_state.fullscreen_state.client_rect;
1360 /* Windowed */
1361 expected_width = expected_client_rect->right;
1362 expected_height = expected_client_rect->bottom;
1364 creation_desc.BufferDesc.Width = 0;
1365 creation_desc.BufferDesc.Height = 0;
1366 creation_desc.Windowed = TRUE;
1367 creation_desc.Flags = 0;
1368 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1369 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1370 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1371 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1372 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1373 result_desc.BufferDesc.Width, expected_width);
1374 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1375 result_desc.BufferDesc.Height, expected_height);
1376 check_swapchain_fullscreen_state(swapchain, &expected_state);
1377 IDXGISwapChain_Release(swapchain);
1379 DestroyWindow(creation_desc.OutputWindow);
1380 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1381 WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
1382 0, 0, 222, 222, 0, 0, 0, 0);
1383 SetRect(&expected_state.fullscreen_state.window_rect, 0, 0, 222, 222);
1384 GetClientRect(creation_desc.OutputWindow, expected_client_rect);
1385 expected_width = expected_client_rect->right;
1386 expected_height = expected_client_rect->bottom;
1388 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1389 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1390 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1391 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1392 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1393 result_desc.BufferDesc.Width, expected_width);
1394 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1395 result_desc.BufferDesc.Height, expected_height);
1396 check_swapchain_fullscreen_state(swapchain, &expected_state);
1397 IDXGISwapChain_Release(swapchain);
1399 DestroyWindow(creation_desc.OutputWindow);
1400 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1401 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1403 /* Fullscreen */
1404 creation_desc.Windowed = FALSE;
1405 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1406 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1407 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1408 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1409 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1410 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1411 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1412 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1413 "GetContainingOutput failed, hr %#x.\n", hr);
1414 check_swapchain_fullscreen_state(swapchain, &initial_state);
1415 IDXGISwapChain_Release(swapchain);
1416 if (hr == DXGI_ERROR_UNSUPPORTED)
1418 win_skip("GetContainingOutput() not supported.\n");
1419 goto done;
1421 if (result_desc.Windowed)
1423 win_skip("Fullscreen not supported.\n");
1424 IDXGIOutput_Release(expected_state.target);
1425 goto done;
1428 creation_desc.BufferDesc.Width = 0;
1429 creation_desc.BufferDesc.Height = 0;
1430 creation_desc.Windowed = FALSE;
1431 creation_desc.Flags = 0;
1432 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1433 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1434 expected_width = expected_client_rect->right - expected_client_rect->left;
1435 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1437 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1438 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1439 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1440 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1441 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1442 result_desc.BufferDesc.Width, expected_width);
1443 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1444 result_desc.BufferDesc.Height, expected_height);
1445 check_swapchain_fullscreen_state(swapchain, &expected_state);
1446 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1447 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1448 check_swapchain_fullscreen_state(swapchain, &initial_state);
1449 IDXGISwapChain_Release(swapchain);
1451 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
1452 creation_desc.BufferDesc.Width = 0;
1453 creation_desc.BufferDesc.Height = 0;
1454 creation_desc.Windowed = FALSE;
1455 creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1456 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1457 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1458 expected_width = expected_client_rect->right - expected_client_rect->left;
1459 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1461 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1462 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1463 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1464 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1465 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1466 result_desc.BufferDesc.Width, expected_width);
1467 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1468 result_desc.BufferDesc.Height, expected_height);
1469 check_swapchain_fullscreen_state(swapchain, &expected_state);
1470 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1471 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1472 check_swapchain_fullscreen_state(swapchain, &initial_state);
1473 IDXGISwapChain_Release(swapchain);
1475 IDXGIOutput_Release(expected_state.target);
1477 done:
1478 IUnknown_Release(obj);
1479 refcount = IDXGIDevice_Release(device);
1480 ok(!refcount, "Device has %u references left.\n", refcount);
1481 refcount = IDXGIAdapter_Release(adapter);
1482 ok(!refcount, "Adapter has %u references left.\n", refcount);
1483 refcount = IDXGIFactory_Release(factory);
1484 ok(!refcount, "Factory has %u references left.\n", refcount);
1485 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1486 DestroyWindow(creation_desc.OutputWindow);
1489 static void test_get_containing_output(void)
1491 unsigned int output_count, output_idx;
1492 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1493 IDXGIOutput *output, *output2;
1494 DXGI_OUTPUT_DESC output_desc;
1495 MONITORINFOEXW monitor_info;
1496 IDXGISwapChain *swapchain;
1497 IDXGIFactory *factory;
1498 IDXGIAdapter *adapter;
1499 POINT points[4 * 16];
1500 IDXGIDevice *device;
1501 unsigned int i, j;
1502 HMONITOR monitor;
1503 ULONG refcount;
1504 HRESULT hr;
1505 BOOL ret;
1507 if (!(device = create_device(0)))
1509 skip("Failed to create device.\n");
1510 return;
1513 hr = IDXGIDevice_GetAdapter(device, &adapter);
1514 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1516 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1517 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1519 swapchain_desc.BufferDesc.Width = 100;
1520 swapchain_desc.BufferDesc.Height = 100;
1521 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1522 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1523 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1524 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1525 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1526 swapchain_desc.SampleDesc.Count = 1;
1527 swapchain_desc.SampleDesc.Quality = 0;
1528 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1529 swapchain_desc.BufferCount = 1;
1530 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1531 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1532 swapchain_desc.Windowed = TRUE;
1533 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1534 swapchain_desc.Flags = 0;
1536 output_count = 0;
1537 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1539 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_count, hr);
1540 IDXGIOutput_Release(output);
1541 ++output_count;
1544 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1545 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1547 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, 0);
1548 ok(!!monitor, "MonitorFromWindow failed.\n");
1550 monitor_info.cbSize = sizeof(monitor_info);
1551 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1552 ok(ret, "Failed to get monitor info.\n");
1554 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1555 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1556 "GetContainingOutput failed, hr %#x.\n", hr);
1557 if (hr == DXGI_ERROR_UNSUPPORTED)
1559 win_skip("GetContainingOutput() not supported.\n");
1560 IDXGISwapChain_Release(swapchain);
1561 goto done;
1564 hr = IDXGIOutput_GetDesc(output, &output_desc);
1565 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1567 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1568 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1569 ok(output != output2, "Got unexpected output pointers %p, %p.\n", output, output2);
1570 check_output_equal(output, output2);
1572 refcount = IDXGIOutput_Release(output);
1573 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1574 refcount = IDXGIOutput_Release(output2);
1575 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1577 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1578 "Got unexpected device name %s, expected %s.\n",
1579 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1580 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1581 "Got unexpected desktop coordinates %s, expected %s.\n",
1582 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1583 wine_dbgstr_rect(&monitor_info.rcMonitor));
1585 output_idx = 0;
1586 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1588 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1590 hr = IDXGIOutput_GetDesc(output, &output_desc);
1591 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1593 /* Move the OutputWindow to the current output. */
1594 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
1595 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
1596 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1597 ok(ret, "SetWindowPos failed.\n");
1599 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1600 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1602 check_output_equal(output, output2);
1604 refcount = IDXGIOutput_Release(output2);
1605 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1606 refcount = IDXGIOutput_Release(output);
1607 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1608 ++output_idx;
1610 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
1611 for (i = 0; i < 4; ++i)
1613 static const POINT offsets[] =
1615 { 0, 0},
1616 {-49, 0}, {-50, 0}, {-51, 0},
1617 { 0, -49}, { 0, -50}, { 0, -51},
1618 {-49, -49}, {-50, -49}, {-51, -49},
1619 {-49, -50}, {-50, -50}, {-51, -50},
1620 {-49, -51}, {-50, -51}, {-51, -51},
1622 unsigned int x, y;
1624 switch (i)
1626 case 0:
1627 x = output_desc.DesktopCoordinates.left;
1628 y = output_desc.DesktopCoordinates.top;
1629 break;
1630 case 1:
1631 x = output_desc.DesktopCoordinates.right;
1632 y = output_desc.DesktopCoordinates.top;
1633 break;
1634 case 2:
1635 x = output_desc.DesktopCoordinates.right;
1636 y = output_desc.DesktopCoordinates.bottom;
1637 break;
1638 case 3:
1639 x = output_desc.DesktopCoordinates.left;
1640 y = output_desc.DesktopCoordinates.bottom;
1641 break;
1644 for (j = 0; j < ARRAY_SIZE(offsets); ++j)
1646 unsigned int idx = ARRAY_SIZE(offsets) * i + j;
1647 assert(idx < ARRAY_SIZE(points));
1648 points[idx].x = x + offsets[j].x;
1649 points[idx].y = y + offsets[j].y;
1653 for (i = 0; i < ARRAY_SIZE(points); ++i)
1655 ret = SetWindowPos(swapchain_desc.OutputWindow, 0, points[i].x, points[i].y,
1656 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1657 ok(ret, "SetWindowPos failed.\n");
1659 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, MONITOR_DEFAULTTONEAREST);
1660 ok(!!monitor, "MonitorFromWindow failed.\n");
1662 monitor_info.cbSize = sizeof(monitor_info);
1663 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1664 ok(ret, "Failed to get monitor info.\n");
1666 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1667 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1668 ok(!!output, "Got unexpected containing output %p.\n", output);
1669 hr = IDXGIOutput_GetDesc(output, &output_desc);
1670 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1671 refcount = IDXGIOutput_Release(output);
1672 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1674 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1675 "Got unexpected device name %s, expected %s.\n",
1676 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1677 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1678 "Got unexpected desktop coordinates %s, expected %s.\n",
1679 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1680 wine_dbgstr_rect(&monitor_info.rcMonitor));
1684 refcount = IDXGISwapChain_Release(swapchain);
1685 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1687 done:
1688 refcount = IDXGIDevice_Release(device);
1689 ok(!refcount, "Device has %u references left.\n", refcount);
1690 refcount = IDXGIAdapter_Release(adapter);
1691 ok(!refcount, "Adapter has %u references left.\n", refcount);
1692 refcount = IDXGIFactory_Release(factory);
1693 ok(!refcount, "Factory has %u references left.\n", refcount);
1694 DestroyWindow(swapchain_desc.OutputWindow);
1697 static void test_swapchain_fullscreen_state(IDXGISwapChain *swapchain,
1698 IDXGIAdapter *adapter, const struct swapchain_fullscreen_state *initial_state)
1700 MONITORINFOEXW monitor_info, *output_monitor_info;
1701 struct swapchain_fullscreen_state expected_state;
1702 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1703 DXGI_OUTPUT_DESC output_desc;
1704 unsigned int i, output_count;
1705 IDXGIOutput *output;
1706 HRESULT hr;
1707 BOOL ret;
1709 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1710 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1712 check_swapchain_fullscreen_state(swapchain, initial_state);
1714 expected_state = *initial_state;
1715 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1716 &swapchain_desc, &initial_state->fullscreen_state.monitor_rect, 800, 600, NULL);
1717 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1718 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1720 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1721 ok(hr == S_OK || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, "Got unexpected hr %#x.\n", hr);
1722 if (FAILED(hr))
1724 skip("Could not change fullscreen state.\n");
1725 IDXGIOutput_Release(expected_state.target);
1726 return;
1728 check_swapchain_fullscreen_state(swapchain, &expected_state);
1730 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1731 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1732 check_swapchain_fullscreen_state(swapchain, &expected_state);
1734 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1735 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1736 check_swapchain_fullscreen_state(swapchain, initial_state);
1738 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1739 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1740 check_swapchain_fullscreen_state(swapchain, initial_state);
1742 IDXGIOutput_Release(expected_state.target);
1743 expected_state.target = NULL;
1745 output_count = 0;
1746 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1748 IDXGIOutput_Release(output);
1749 ++output_count;
1752 output_monitor_info = HeapAlloc(GetProcessHeap(), 0, output_count * sizeof(*output_monitor_info));
1753 ok(!!output_monitor_info, "Failed to allocate memory.\n");
1754 for (i = 0; i < output_count; ++i)
1756 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1757 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1759 hr = IDXGIOutput_GetDesc(output, &output_desc);
1760 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1762 output_monitor_info[i].cbSize = sizeof(*output_monitor_info);
1763 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&output_monitor_info[i]);
1764 ok(ret, "Failed to get monitor info.\n");
1766 IDXGIOutput_Release(output);
1769 for (i = 0; i < output_count; ++i)
1771 RECT orig_monitor_rect = output_monitor_info[i].rcMonitor;
1772 IDXGIOutput *target;
1773 BOOL fullscreen;
1775 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1776 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1777 hr = IDXGIOutput_GetDesc(output, &output_desc);
1778 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1780 expected_state = *initial_state;
1781 expected_state.target = output;
1782 expected_state.fullscreen_state.monitor = output_desc.Monitor;
1783 expected_state.fullscreen_state.monitor_rect = orig_monitor_rect;
1784 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1785 &swapchain_desc, &orig_monitor_rect, 800, 600, NULL);
1787 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1788 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1789 check_swapchain_fullscreen_state(swapchain, &expected_state);
1791 target = NULL;
1792 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1793 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1794 ok(target == output, "Got target pointer %p, expected %p.\n", target, output);
1795 IDXGIOutput_Release(target);
1796 fullscreen = FALSE;
1797 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1798 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1799 ok(fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1801 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1802 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1803 check_swapchain_fullscreen_state(swapchain, &expected_state);
1804 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, output);
1805 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1806 check_swapchain_fullscreen_state(swapchain, &expected_state);
1807 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1808 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1809 check_swapchain_fullscreen_state(swapchain, initial_state);
1811 fullscreen = TRUE;
1812 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1813 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1814 ok(!fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1816 check_swapchain_fullscreen_state(swapchain, initial_state);
1817 monitor_info.cbSize = sizeof(monitor_info);
1818 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1819 ok(ret, "Failed to get monitor info.\n");
1820 ok(EqualRect(&monitor_info.rcMonitor, &orig_monitor_rect), "Got monitor rect %s, expected %s.\n",
1821 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&orig_monitor_rect));
1823 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1824 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1826 IDXGIOutput_Release(output);
1829 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1830 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1831 check_swapchain_fullscreen_state(swapchain, initial_state);
1833 for (i = 0; i < output_count; ++i)
1835 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1836 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1838 hr = IDXGIOutput_GetDesc(output, &output_desc);
1839 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1841 monitor_info.cbSize = sizeof(monitor_info);
1842 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1843 ok(ret, "Failed to get monitor info.\n");
1845 ok(EqualRect(&monitor_info.rcMonitor, &output_monitor_info[i].rcMonitor),
1846 "Got monitor rect %s, expected %s.\n",
1847 wine_dbgstr_rect(&monitor_info.rcMonitor),
1848 wine_dbgstr_rect(&output_monitor_info[i].rcMonitor));
1850 IDXGIOutput_Release(output);
1853 HeapFree(GetProcessHeap(), 0, output_monitor_info);
1856 static void test_set_fullscreen(void)
1858 struct swapchain_fullscreen_state initial_state;
1859 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1860 IDXGISwapChain *swapchain;
1861 IDXGIFactory *factory;
1862 IDXGIAdapter *adapter;
1863 IDXGIDevice *device;
1864 ULONG refcount;
1865 HRESULT hr;
1867 if (!(device = create_device(0)))
1869 skip("Failed to create device.\n");
1870 return;
1873 hr = IDXGIDevice_GetAdapter(device, &adapter);
1874 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1876 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1877 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1879 swapchain_desc.BufferDesc.Width = 800;
1880 swapchain_desc.BufferDesc.Height = 600;
1881 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1882 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1883 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1884 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1885 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1886 swapchain_desc.SampleDesc.Count = 1;
1887 swapchain_desc.SampleDesc.Quality = 0;
1888 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1889 swapchain_desc.BufferCount = 1;
1890 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1891 swapchain_desc.Windowed = TRUE;
1892 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1893 swapchain_desc.Flags = 0;
1895 memset(&initial_state, 0, sizeof(initial_state));
1896 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
1897 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1898 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1899 check_swapchain_fullscreen_state(swapchain, &initial_state);
1900 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1901 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE ||
1902 broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */
1903 "SetFullscreenState failed, hr %#x.\n", hr);
1904 if (FAILED(hr))
1906 skip("Could not change fullscreen state.\n");
1907 goto done;
1909 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1910 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1911 refcount = IDXGISwapChain_Release(swapchain);
1912 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1914 DestroyWindow(swapchain_desc.OutputWindow);
1915 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1916 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1917 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1918 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1919 check_swapchain_fullscreen_state(swapchain, &initial_state);
1920 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1921 refcount = IDXGISwapChain_Release(swapchain);
1922 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1924 DestroyWindow(swapchain_desc.OutputWindow);
1925 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1926 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1927 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1928 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1929 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1930 check_swapchain_fullscreen_state(swapchain, &initial_state);
1931 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1933 done:
1934 refcount = IDXGISwapChain_Release(swapchain);
1935 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1936 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1937 DestroyWindow(swapchain_desc.OutputWindow);
1939 IDXGIAdapter_Release(adapter);
1940 refcount = IDXGIDevice_Release(device);
1941 ok(!refcount, "Device has %u references left.\n", refcount);
1942 refcount = IDXGIFactory_Release(factory);
1943 ok(!refcount, "Factory has %u references left.\n", refcount);
1946 static void test_default_fullscreen_target_output(void)
1948 IDXGIOutput *output, *containing_output, *target;
1949 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1950 DXGI_OUTPUT_DESC output_desc;
1951 IDXGISwapChain *swapchain;
1952 unsigned int output_idx;
1953 IDXGIFactory *factory;
1954 IDXGIAdapter *adapter;
1955 IDXGIDevice *device;
1956 ULONG refcount;
1957 HRESULT hr;
1958 BOOL ret;
1960 if (!(device = create_device(0)))
1962 skip("Failed to create device.\n");
1963 return;
1966 hr = IDXGIDevice_GetAdapter(device, &adapter);
1967 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1969 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1970 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1972 swapchain_desc.BufferDesc.Width = 100;
1973 swapchain_desc.BufferDesc.Height = 100;
1974 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1975 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1976 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1977 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1978 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1979 swapchain_desc.SampleDesc.Count = 1;
1980 swapchain_desc.SampleDesc.Quality = 0;
1981 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1982 swapchain_desc.BufferCount = 1;
1983 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1984 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1985 swapchain_desc.Windowed = TRUE;
1986 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1987 swapchain_desc.Flags = 0;
1989 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1990 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1992 output_idx = 0;
1993 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1995 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1997 hr = IDXGIOutput_GetDesc(output, &output_desc);
1998 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2000 /* Move the OutputWindow to the current output. */
2001 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
2002 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
2003 0, 0, SWP_NOSIZE | SWP_NOZORDER);
2004 ok(ret, "SetWindowPos failed.\n");
2006 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
2007 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2008 "GetContainingOutput failed, hr %#x.\n", hr);
2009 if (hr == DXGI_ERROR_UNSUPPORTED)
2011 win_skip("GetContainingOutput() not supported.\n");
2012 IDXGIOutput_Release(output);
2013 goto done;
2016 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
2017 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
2018 "SetFullscreenState failed, hr %#x.\n", hr);
2019 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
2021 skip("Could not change fullscreen state.\n");
2022 IDXGIOutput_Release(containing_output);
2023 IDXGIOutput_Release(output);
2024 goto done;
2027 target = NULL;
2028 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
2029 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
2030 ok(target != containing_output, "Got unexpected output pointers %p, %p.\n",
2031 target, containing_output);
2032 check_output_equal(target, containing_output);
2034 refcount = IDXGIOutput_Release(containing_output);
2035 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
2037 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
2038 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
2039 ok(containing_output == target, "Got unexpected containing output %p, expected %p.\n",
2040 containing_output, target);
2041 refcount = IDXGIOutput_Release(containing_output);
2042 ok(refcount >= 2, "Got unexpected refcount %u.\n", refcount);
2043 refcount = IDXGIOutput_Release(target);
2044 ok(refcount >= 1, "Got unexpected refcount %u.\n", refcount);
2046 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2047 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2049 IDXGIOutput_Release(output);
2050 ++output_idx;
2053 done:
2054 refcount = IDXGISwapChain_Release(swapchain);
2055 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2057 refcount = IDXGIDevice_Release(device);
2058 ok(!refcount, "Device has %u references left.\n", refcount);
2059 refcount = IDXGIAdapter_Release(adapter);
2060 ok(!refcount, "Adapter has %u references left.\n", refcount);
2061 refcount = IDXGIFactory_Release(factory);
2062 ok(!refcount, "Factory has %u references left.\n", refcount);
2063 DestroyWindow(swapchain_desc.OutputWindow);
2066 static void test_windowed_resize_target(IDXGISwapChain *swapchain, HWND window,
2067 struct swapchain_fullscreen_state *state)
2069 struct swapchain_fullscreen_state expected_state;
2070 struct fullscreen_state *e;
2071 DXGI_MODE_DESC mode;
2072 RECT window_rect;
2073 unsigned int i;
2074 HRESULT hr;
2075 BOOL ret;
2077 static const struct
2079 unsigned int width, height;
2081 sizes[] =
2083 {200, 200},
2084 {400, 200},
2085 {400, 400},
2086 {600, 800},
2087 {1000, 600},
2088 {1600, 100},
2089 {2000, 1000},
2092 check_swapchain_fullscreen_state(swapchain, state);
2093 expected_state = *state;
2094 e = &expected_state.fullscreen_state;
2096 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
2098 SetRect(&e->client_rect, 0, 0, sizes[i].width, sizes[i].height);
2099 e->window_rect = e->client_rect;
2100 ret = AdjustWindowRectEx(&e->window_rect, GetWindowLongW(window, GWL_STYLE),
2101 FALSE, GetWindowLongW(window, GWL_EXSTYLE));
2102 ok(ret, "AdjustWindowRectEx failed.\n");
2103 if (GetMenu(window))
2104 e->client_rect.bottom -= GetSystemMetrics(SM_CYMENU);
2105 SetRect(&e->window_rect, 0, 0,
2106 e->window_rect.right - e->window_rect.left,
2107 e->window_rect.bottom - e->window_rect.top);
2108 GetWindowRect(window, &window_rect);
2109 OffsetRect(&e->window_rect, window_rect.left, window_rect.top);
2110 if (e->window_rect.right >= e->monitor_rect.right
2111 || e->window_rect.bottom >= e->monitor_rect.bottom)
2113 skip("Test %u: Window %s does not fit on screen %s.\n",
2114 i, wine_dbgstr_rect(&e->window_rect), wine_dbgstr_rect(&e->monitor_rect));
2115 continue;
2118 memset(&mode, 0, sizeof(mode));
2119 mode.Width = sizes[i].width;
2120 mode.Height = sizes[i].height;
2121 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
2122 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2123 check_swapchain_fullscreen_state(swapchain, &expected_state);
2126 ret = MoveWindow(window, 0, 0, 0, 0, TRUE);
2127 ok(ret, "MoveWindow failed.\n");
2128 GetWindowRect(window, &e->window_rect);
2129 GetClientRect(window, &e->client_rect);
2130 ret = MoveWindow(window, 0, 0, 200, 200, TRUE);
2132 memset(&mode, 0, sizeof(mode));
2133 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
2134 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2135 check_swapchain_fullscreen_state(swapchain, &expected_state);
2137 GetWindowRect(window, &e->window_rect);
2138 GetClientRect(window, &e->client_rect);
2139 *state = expected_state;
2142 static void test_fullscreen_resize_target(IDXGISwapChain *swapchain,
2143 const struct swapchain_fullscreen_state *initial_state)
2145 struct swapchain_fullscreen_state expected_state;
2146 DXGI_SWAP_CHAIN_DESC swapchain_desc;
2147 DXGI_OUTPUT_DESC output_desc;
2148 unsigned int i, mode_count;
2149 DXGI_MODE_DESC *modes;
2150 IDXGIOutput *target;
2151 HRESULT hr;
2153 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2154 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2156 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
2157 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
2159 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
2160 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
2161 "Failed to list modes, hr %#x.\n", hr);
2162 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
2164 win_skip("GetDisplayModeList() not supported.\n");
2165 IDXGIOutput_Release(target);
2166 return;
2169 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
2170 ok(!!modes, "Failed to allocate memory.\n");
2172 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
2173 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
2175 expected_state = *initial_state;
2176 for (i = 0; i < min(mode_count, 20); ++i)
2178 /* FIXME: Modes with scaling aren't fully tested. */
2179 if (!(swapchain_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
2180 && modes[i].Scaling != DXGI_MODE_SCALING_UNSPECIFIED)
2181 continue;
2183 hr = IDXGIOutput_GetDesc(target, &output_desc);
2184 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2186 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2187 &swapchain_desc, &output_desc.DesktopCoordinates, modes[i].Width, modes[i].Height, NULL);
2189 hr = IDXGISwapChain_ResizeTarget(swapchain, &modes[i]);
2190 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2191 check_swapchain_fullscreen_state(swapchain, &expected_state);
2193 hr = IDXGIOutput_GetDesc(target, &output_desc);
2194 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2195 ok(EqualRect(&output_desc.DesktopCoordinates, &expected_state.fullscreen_state.monitor_rect),
2196 "Got desktop coordinates %s, expected %s.\n",
2197 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
2198 wine_dbgstr_rect(&expected_state.fullscreen_state.monitor_rect));
2201 HeapFree(GetProcessHeap(), 0, modes);
2202 IDXGIOutput_Release(target);
2205 static void test_resize_target(void)
2207 struct swapchain_fullscreen_state initial_state, expected_state;
2208 DXGI_SWAP_CHAIN_DESC swapchain_desc;
2209 IDXGISwapChain *swapchain;
2210 IDXGIFactory *factory;
2211 IDXGIAdapter *adapter;
2212 IDXGIDevice *device;
2213 unsigned int i;
2214 ULONG refcount;
2215 HRESULT hr;
2217 static const struct
2219 POINT origin;
2220 BOOL fullscreen;
2221 BOOL menu;
2222 unsigned int flags;
2224 tests[] =
2226 {{ 0, 0}, TRUE, FALSE, 0},
2227 {{10, 10}, TRUE, FALSE, 0},
2228 {{ 0, 0}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2229 {{10, 10}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2230 {{ 0, 0}, FALSE, FALSE, 0},
2231 {{ 0, 0}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2232 {{10, 10}, FALSE, FALSE, 0},
2233 {{10, 10}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2234 {{ 0, 0}, FALSE, TRUE, 0},
2235 {{ 0, 0}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2236 {{10, 10}, FALSE, TRUE, 0},
2237 {{10, 10}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2240 if (!(device = create_device(0)))
2242 skip("Failed to create device.\n");
2243 return;
2246 hr = IDXGIDevice_GetAdapter(device, &adapter);
2247 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2249 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2250 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2252 swapchain_desc.BufferDesc.Width = 800;
2253 swapchain_desc.BufferDesc.Height = 600;
2254 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2255 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2256 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2257 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2258 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2259 swapchain_desc.SampleDesc.Count = 1;
2260 swapchain_desc.SampleDesc.Quality = 0;
2261 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2262 swapchain_desc.BufferCount = 1;
2263 swapchain_desc.Windowed = TRUE;
2264 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2265 swapchain_desc.Flags = 0;
2267 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2269 swapchain_desc.Flags = tests[i].flags;
2270 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0,
2271 tests[i].origin.x, tests[i].origin.y, 400, 200, 0, 0, 0, 0);
2272 if (tests[i].menu)
2274 HMENU menu_bar = CreateMenu();
2275 HMENU menu = CreateMenu();
2276 AppendMenuA(menu_bar, MF_POPUP, (UINT_PTR)menu, "Menu");
2277 SetMenu(swapchain_desc.OutputWindow, menu_bar);
2280 memset(&initial_state, 0, sizeof(initial_state));
2281 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
2283 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2284 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2285 check_swapchain_fullscreen_state(swapchain, &initial_state);
2287 expected_state = initial_state;
2288 if (tests[i].fullscreen)
2290 expected_state.fullscreen = TRUE;
2291 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2292 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect, 800, 600, NULL);
2293 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
2294 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2295 "GetContainingOutput failed, hr %#x.\n", hr);
2296 if (hr == DXGI_ERROR_UNSUPPORTED)
2298 win_skip("GetContainingOutput() not supported.\n");
2299 IDXGISwapChain_Release(swapchain);
2300 DestroyWindow(swapchain_desc.OutputWindow);
2301 continue;
2304 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
2305 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
2306 "SetFullscreenState failed, hr %#x.\n", hr);
2307 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
2309 skip("Could not change fullscreen state.\n");
2310 IDXGIOutput_Release(expected_state.target);
2311 IDXGISwapChain_Release(swapchain);
2312 DestroyWindow(swapchain_desc.OutputWindow);
2313 continue;
2316 check_swapchain_fullscreen_state(swapchain, &expected_state);
2318 hr = IDXGISwapChain_ResizeTarget(swapchain, NULL);
2319 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2320 check_swapchain_fullscreen_state(swapchain, &expected_state);
2322 if (tests[i].fullscreen)
2324 test_fullscreen_resize_target(swapchain, &expected_state);
2326 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2327 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2328 check_swapchain_fullscreen_state(swapchain, &initial_state);
2329 IDXGIOutput_Release(expected_state.target);
2330 check_swapchain_fullscreen_state(swapchain, &initial_state);
2331 expected_state = initial_state;
2333 else
2335 test_windowed_resize_target(swapchain, swapchain_desc.OutputWindow, &expected_state);
2337 check_swapchain_fullscreen_state(swapchain, &expected_state);
2340 refcount = IDXGISwapChain_Release(swapchain);
2341 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2342 check_window_fullscreen_state(swapchain_desc.OutputWindow, &expected_state.fullscreen_state);
2343 DestroyWindow(swapchain_desc.OutputWindow);
2346 IDXGIAdapter_Release(adapter);
2347 refcount = IDXGIDevice_Release(device);
2348 ok(!refcount, "Device has %u references left.\n", refcount);
2349 refcount = IDXGIFactory_Release(factory);
2350 ok(!refcount, "Factory has %u references left.\n", refcount);
2353 static void test_inexact_modes(void)
2355 struct swapchain_fullscreen_state initial_state, expected_state;
2356 DXGI_SWAP_CHAIN_DESC swapchain_desc, result_desc;
2357 IDXGIOutput *output = NULL;
2358 IDXGISwapChain *swapchain;
2359 IDXGIFactory *factory;
2360 IDXGIAdapter *adapter;
2361 IDXGIDevice *device;
2362 unsigned int i;
2363 ULONG refcount;
2364 HRESULT hr;
2366 static const struct
2368 unsigned int width, height;
2370 sizes[] =
2372 {101, 101},
2373 {203, 204},
2374 {799, 601},
2377 if (!(device = create_device(0)))
2379 skip("Failed to create device.\n");
2380 return;
2383 hr = IDXGIDevice_GetAdapter(device, &adapter);
2384 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2386 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2387 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2389 swapchain_desc.BufferDesc.Width = 800;
2390 swapchain_desc.BufferDesc.Height = 600;
2391 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2392 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2393 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2394 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2395 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2396 swapchain_desc.SampleDesc.Count = 1;
2397 swapchain_desc.SampleDesc.Quality = 0;
2398 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2399 swapchain_desc.BufferCount = 1;
2400 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2401 swapchain_desc.Windowed = FALSE;
2402 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2403 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
2405 memset(&initial_state, 0, sizeof(initial_state));
2406 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
2408 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2409 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2410 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2411 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2412 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2413 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2414 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
2415 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2416 "GetContainingOutput failed, hr %#x.\n", hr);
2417 refcount = IDXGISwapChain_Release(swapchain);
2418 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2419 if (hr == DXGI_ERROR_UNSUPPORTED)
2421 win_skip("GetContainingOutput() not supported.\n");
2422 goto done;
2424 if (result_desc.Windowed)
2426 win_skip("Fullscreen not supported.\n");
2427 goto done;
2430 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
2432 for (i = 0; i < ARRAY_SIZE(sizes); ++i)
2434 /* Test CreateSwapChain(). */
2435 swapchain_desc.BufferDesc.Width = sizes[i].width;
2436 swapchain_desc.BufferDesc.Height = sizes[i].height;
2437 swapchain_desc.Windowed = FALSE;
2439 expected_state = initial_state;
2440 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2441 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect,
2442 sizes[i].width, sizes[i].height, output);
2444 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2445 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2447 check_swapchain_fullscreen_state(swapchain, &expected_state);
2448 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2449 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2450 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2451 result_desc.BufferDesc.Width, sizes[i].width);
2452 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2453 result_desc.BufferDesc.Height, sizes[i].height);
2455 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2456 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2457 check_swapchain_fullscreen_state(swapchain, &initial_state);
2459 refcount = IDXGISwapChain_Release(swapchain);
2460 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2462 /* Test SetFullscreenState(). */
2463 swapchain_desc.BufferDesc.Width = sizes[i].width;
2464 swapchain_desc.BufferDesc.Height = sizes[i].height;
2465 swapchain_desc.Windowed = TRUE;
2467 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2468 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2470 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2471 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2473 check_swapchain_fullscreen_state(swapchain, &expected_state);
2474 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2475 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2476 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2477 result_desc.BufferDesc.Width, sizes[i].width);
2478 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2479 result_desc.BufferDesc.Height, sizes[i].height);
2481 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2482 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2483 check_swapchain_fullscreen_state(swapchain, &initial_state);
2485 refcount = IDXGISwapChain_Release(swapchain);
2486 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2488 /* Test ResizeTarget(). */
2489 swapchain_desc.BufferDesc.Width = 800;
2490 swapchain_desc.BufferDesc.Height = 600;
2491 swapchain_desc.Windowed = TRUE;
2493 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2494 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2496 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2497 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2499 swapchain_desc.BufferDesc.Width = sizes[i].width;
2500 swapchain_desc.BufferDesc.Height = sizes[i].height;
2501 hr = IDXGISwapChain_ResizeTarget(swapchain, &swapchain_desc.BufferDesc);
2502 ok(SUCCEEDED(hr), "ResizeTarget failed, hr %#x.\n", hr);
2504 check_swapchain_fullscreen_state(swapchain, &expected_state);
2505 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2506 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2507 ok(result_desc.BufferDesc.Width == 800, "Got width %u.\n", result_desc.BufferDesc.Width);
2508 ok(result_desc.BufferDesc.Height == 600, "Got height %u.\n", result_desc.BufferDesc.Height);
2510 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2511 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2512 check_swapchain_fullscreen_state(swapchain, &initial_state);
2514 refcount = IDXGISwapChain_Release(swapchain);
2515 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2518 done:
2519 if (output)
2520 IDXGIOutput_Release(output);
2521 IDXGIAdapter_Release(adapter);
2522 refcount = IDXGIDevice_Release(device);
2523 ok(!refcount, "Device has %u references left.\n", refcount);
2524 refcount = IDXGIFactory_Release(factory);
2525 ok(!refcount, "Factory has %u references left.\n", refcount);
2528 static void test_create_factory(void)
2530 IUnknown *iface;
2531 ULONG refcount;
2532 HRESULT hr;
2534 iface = (void *)0xdeadbeef;
2535 hr = CreateDXGIFactory(&IID_IDXGIDevice, (void **)&iface);
2536 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2537 ok(!iface, "Got unexpected iface %p.\n", iface);
2539 hr = CreateDXGIFactory(&IID_IUnknown, (void **)&iface);
2540 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2541 IUnknown_Release(iface);
2543 hr = CreateDXGIFactory(&IID_IDXGIObject, (void **)&iface);
2544 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2545 IUnknown_Release(iface);
2547 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&iface);
2548 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2549 check_interface(iface, &IID_IDXGIFactory1, FALSE, FALSE);
2550 IUnknown_Release(iface);
2552 iface = (void *)0xdeadbeef;
2553 hr = CreateDXGIFactory(&IID_IDXGIFactory1, (void **)&iface);
2554 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2555 ok(!iface, "Got unexpected iface %p.\n", iface);
2557 iface = NULL;
2558 hr = CreateDXGIFactory(&IID_IDXGIFactory2, (void **)&iface);
2559 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
2560 "Got unexpected hr %#x.\n", hr);
2561 if (SUCCEEDED(hr))
2563 refcount = IUnknown_Release(iface);
2564 ok(!refcount, "Factory has %u references left.\n", refcount);
2567 if (!pCreateDXGIFactory1)
2569 win_skip("CreateDXGIFactory1 not available.\n");
2570 return;
2573 iface = (void *)0xdeadbeef;
2574 hr = pCreateDXGIFactory1(&IID_IDXGIDevice, (void **)&iface);
2575 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2576 ok(!iface, "Got unexpected iface %p.\n", iface);
2578 hr = pCreateDXGIFactory1(&IID_IUnknown, (void **)&iface);
2579 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2580 IUnknown_Release(iface);
2582 hr = pCreateDXGIFactory1(&IID_IDXGIObject, (void **)&iface);
2583 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2584 IUnknown_Release(iface);
2586 hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&iface);
2587 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2588 check_interface(iface, &IID_IDXGIFactory1, TRUE, FALSE);
2589 refcount = IUnknown_Release(iface);
2590 ok(!refcount, "Factory has %u references left.\n", refcount);
2592 hr = pCreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&iface);
2593 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr);
2594 IUnknown_Release(iface);
2596 iface = NULL;
2597 hr = pCreateDXGIFactory1(&IID_IDXGIFactory2, (void **)&iface);
2598 ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
2599 "Got unexpected hr %#x.\n", hr);
2600 if (SUCCEEDED(hr))
2602 refcount = IUnknown_Release(iface);
2603 ok(!refcount, "Factory has %u references left.\n", refcount);
2606 if (!pCreateDXGIFactory2)
2608 win_skip("CreateDXGIFactory2 not available.\n");
2609 return;
2612 hr = pCreateDXGIFactory2(0, &IID_IDXGIFactory3, (void **)&iface);
2613 ok(hr == S_OK, "Failed to create factory, hr %#x.\n", hr);
2614 check_interface(iface, &IID_IDXGIFactory, TRUE, FALSE);
2615 check_interface(iface, &IID_IDXGIFactory1, TRUE, FALSE);
2616 check_interface(iface, &IID_IDXGIFactory2, TRUE, FALSE);
2617 check_interface(iface, &IID_IDXGIFactory3, TRUE, FALSE);
2618 /* Not available on all Windows versions. */
2619 check_interface(iface, &IID_IDXGIFactory4, TRUE, TRUE);
2620 check_interface(iface, &IID_IDXGIFactory5, TRUE, TRUE);
2621 refcount = IUnknown_Release(iface);
2622 ok(!refcount, "Factory has %u references left.\n", refcount);
2624 hr = pCreateDXGIFactory2(0, &IID_IDXGIFactory, (void **)&iface);
2625 ok(hr == S_OK, "Failed to create factory, hr %#x.\n", hr);
2626 check_interface(iface, &IID_IDXGIFactory, TRUE, FALSE);
2627 check_interface(iface, &IID_IDXGIFactory1, TRUE, FALSE);
2628 check_interface(iface, &IID_IDXGIFactory2, TRUE, FALSE);
2629 check_interface(iface, &IID_IDXGIFactory3, TRUE, FALSE);
2630 refcount = IUnknown_Release(iface);
2631 ok(!refcount, "Factory has %u references left.\n", refcount);
2634 static void test_private_data(void)
2636 ULONG refcount, expected_refcount;
2637 IDXGIDevice *device;
2638 HRESULT hr;
2639 IDXGIDevice *test_object;
2640 IUnknown *ptr;
2641 static const DWORD data[] = {1, 2, 3, 4};
2642 UINT size;
2643 static const GUID dxgi_private_data_test_guid =
2645 0xfdb37466,
2646 0x428f,
2647 0x4edf,
2648 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
2650 static const GUID dxgi_private_data_test_guid2 =
2652 0x2e5afac2,
2653 0x87b5,
2654 0x4c10,
2655 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
2658 if (!(device = create_device(0)))
2660 skip("Failed to create device, skipping tests.\n");
2661 return;
2664 test_object = create_device(0);
2666 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
2667 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
2668 * NULL interface is not considered a clear but as setting an interface pointer that
2669 * happens to be NULL. */
2670 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 0, NULL);
2671 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2672 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2673 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2674 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2675 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2676 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2677 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2679 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2680 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2681 size = sizeof(ptr) * 2;
2682 ptr = (IUnknown *)0xdeadbeef;
2683 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2684 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2685 ok(!ptr, "Got unexpected pointer %p.\n", ptr);
2686 ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size);
2688 refcount = get_refcount((IUnknown *)test_object);
2689 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2690 (IUnknown *)test_object);
2691 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2692 expected_refcount = refcount + 1;
2693 refcount = get_refcount((IUnknown *)test_object);
2694 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2695 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2696 (IUnknown *)test_object);
2697 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2698 refcount = get_refcount((IUnknown *)test_object);
2699 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2701 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2702 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2703 expected_refcount--;
2704 refcount = get_refcount((IUnknown *)test_object);
2705 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2707 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2708 (IUnknown *)test_object);
2709 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2710 size = sizeof(data);
2711 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, size, data);
2712 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2713 refcount = get_refcount((IUnknown *)test_object);
2714 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2715 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2716 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2717 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2718 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2720 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2721 (IUnknown *)test_object);
2722 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2723 expected_refcount++;
2724 size = 2 * sizeof(ptr);
2725 ptr = NULL;
2726 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2727 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2728 ok(size == sizeof(test_object), "Got unexpected size %u.\n", size);
2729 expected_refcount++;
2730 refcount = get_refcount((IUnknown *)test_object);
2731 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2732 if (ptr)
2733 IUnknown_Release(ptr);
2734 expected_refcount--;
2736 ptr = (IUnknown *)0xdeadbeef;
2737 size = 1;
2738 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2739 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2740 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2741 size = 2 * sizeof(ptr);
2742 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2743 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2744 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2745 refcount = get_refcount((IUnknown *)test_object);
2746 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2748 size = 1;
2749 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2750 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
2751 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2752 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2753 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, NULL, NULL);
2754 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2755 size = 0xdeadbabe;
2756 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, &size, &ptr);
2757 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
2758 ok(size == 0, "Got unexpected size %u.\n", size);
2759 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2760 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, NULL, &ptr);
2761 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2762 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2764 refcount = IDXGIDevice_Release(device);
2765 ok(!refcount, "Device has %u references left.\n", refcount);
2766 refcount = IDXGIDevice_Release(test_object);
2767 ok(!refcount, "Test object has %u references left.\n", refcount);
2770 static void test_swapchain_resize(void)
2772 DXGI_SWAP_CHAIN_DESC swapchain_desc;
2773 D3D10_TEXTURE2D_DESC texture_desc;
2774 DXGI_SURFACE_DESC surface_desc;
2775 IDXGISwapChain *swapchain;
2776 ID3D10Texture2D *texture;
2777 IDXGISurface *surface;
2778 IDXGIAdapter *adapter;
2779 IDXGIFactory *factory;
2780 IDXGIDevice *device;
2781 RECT client_rect, r;
2782 ULONG refcount;
2783 HWND window;
2784 HRESULT hr;
2785 BOOL ret;
2787 if (!(device = create_device(0)))
2789 skip("Failed to create device, skipping tests.\n");
2790 return;
2792 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2793 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2794 ret = GetClientRect(window, &client_rect);
2795 ok(ret, "Failed to get client rect.\n");
2797 hr = IDXGIDevice_GetAdapter(device, &adapter);
2798 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
2799 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2800 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
2801 IDXGIAdapter_Release(adapter);
2803 swapchain_desc.BufferDesc.Width = 640;
2804 swapchain_desc.BufferDesc.Height = 480;
2805 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2806 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2807 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2808 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2809 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2810 swapchain_desc.SampleDesc.Count = 1;
2811 swapchain_desc.SampleDesc.Quality = 0;
2812 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2813 swapchain_desc.BufferCount = 1;
2814 swapchain_desc.OutputWindow = window;
2815 swapchain_desc.Windowed = TRUE;
2816 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2817 swapchain_desc.Flags = 0;
2819 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2820 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
2821 IDXGIFactory_Release(factory);
2822 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2823 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2824 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2825 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2827 ret = GetClientRect(window, &r);
2828 ok(ret, "Failed to get client rect.\n");
2829 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2830 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2832 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
2833 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2834 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2835 ok(swapchain_desc.BufferDesc.Width == 640,
2836 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2837 ok(swapchain_desc.BufferDesc.Height == 480,
2838 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2839 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2840 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2841 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2842 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2843 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2844 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2845 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2846 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2847 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2848 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2849 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2850 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2851 ok(swapchain_desc.SampleDesc.Count == 1,
2852 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2853 ok(!swapchain_desc.SampleDesc.Quality,
2854 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2855 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2856 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2857 ok(swapchain_desc.BufferCount == 1,
2858 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2859 ok(swapchain_desc.OutputWindow == window,
2860 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2861 ok(swapchain_desc.Windowed,
2862 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2863 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2864 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2865 ok(!swapchain_desc.Flags,
2866 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2868 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2869 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2870 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2871 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2872 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2873 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2874 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2876 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2877 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2878 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2879 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2880 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2881 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2882 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2883 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2884 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2885 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2886 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2887 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2889 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2890 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2892 ret = GetClientRect(window, &r);
2893 ok(ret, "Failed to get client rect.\n");
2894 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2895 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2897 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
2898 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2899 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2900 ok(swapchain_desc.BufferDesc.Width == 640,
2901 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2902 ok(swapchain_desc.BufferDesc.Height == 480,
2903 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2904 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2905 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2906 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2907 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2908 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2909 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2910 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2911 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2912 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2913 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2914 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2915 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2916 ok(swapchain_desc.SampleDesc.Count == 1,
2917 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2918 ok(!swapchain_desc.SampleDesc.Quality,
2919 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2920 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2921 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2922 ok(swapchain_desc.BufferCount == 1,
2923 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2924 ok(swapchain_desc.OutputWindow == window,
2925 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2926 ok(swapchain_desc.Windowed,
2927 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2928 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2929 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2930 ok(!swapchain_desc.Flags,
2931 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2933 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2934 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2935 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2936 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2937 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2938 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2939 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2941 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2942 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2943 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2944 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2945 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2946 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2947 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2948 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2949 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2950 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2951 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2952 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2954 ID3D10Texture2D_Release(texture);
2955 IDXGISurface_Release(surface);
2956 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2957 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
2958 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2959 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2960 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2961 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2963 ret = GetClientRect(window, &r);
2964 ok(ret, "Failed to get client rect.\n");
2965 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2966 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2968 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
2969 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2970 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2971 ok(swapchain_desc.BufferDesc.Width == 320,
2972 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2973 ok(swapchain_desc.BufferDesc.Height == 240,
2974 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2975 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2976 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2977 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2978 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2979 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2980 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2981 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
2982 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2983 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2984 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2985 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2986 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2987 ok(swapchain_desc.SampleDesc.Count == 1,
2988 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2989 ok(!swapchain_desc.SampleDesc.Quality,
2990 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2991 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2992 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2993 ok(swapchain_desc.BufferCount == 1,
2994 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2995 ok(swapchain_desc.OutputWindow == window,
2996 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2997 ok(swapchain_desc.Windowed,
2998 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2999 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
3000 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
3001 ok(!swapchain_desc.Flags,
3002 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
3004 hr = IDXGISurface_GetDesc(surface, &surface_desc);
3005 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
3006 ok(surface_desc.Width == 320, "Got unexpected Width %u.\n", surface_desc.Width);
3007 ok(surface_desc.Height == 240, "Got unexpected Height %u.\n", surface_desc.Height);
3008 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", surface_desc.Format);
3009 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
3010 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
3012 ID3D10Texture2D_GetDesc(texture, &texture_desc);
3013 ok(texture_desc.Width == 320, "Got unexpected Width %u.\n", texture_desc.Width);
3014 ok(texture_desc.Height == 240, "Got unexpected Height %u.\n", texture_desc.Height);
3015 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
3016 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
3017 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", texture_desc.Format);
3018 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
3019 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
3020 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
3021 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
3022 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
3023 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
3025 ID3D10Texture2D_Release(texture);
3026 IDXGISurface_Release(surface);
3028 hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
3029 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
3031 memset(&swapchain_desc, 0, sizeof(swapchain_desc));
3032 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
3033 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
3034 ok(swapchain_desc.BufferDesc.Width == client_rect.right - client_rect.left,
3035 "Got unexpected BufferDesc.Width %u, expected %u.\n",
3036 swapchain_desc.BufferDesc.Width, client_rect.right - client_rect.left);
3037 ok(swapchain_desc.BufferDesc.Height == client_rect.bottom - client_rect.top,
3038 "Got unexpected bufferDesc.Height %u, expected %u.\n",
3039 swapchain_desc.BufferDesc.Height, client_rect.bottom - client_rect.top);
3040 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
3041 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
3042 swapchain_desc.BufferDesc.RefreshRate.Numerator);
3043 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
3044 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
3045 swapchain_desc.BufferDesc.RefreshRate.Denominator);
3046 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
3047 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
3048 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
3049 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
3050 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
3051 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
3052 ok(swapchain_desc.SampleDesc.Count == 1,
3053 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
3054 ok(!swapchain_desc.SampleDesc.Quality,
3055 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
3056 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
3057 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
3058 ok(swapchain_desc.BufferCount == 1,
3059 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
3060 ok(swapchain_desc.OutputWindow == window,
3061 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
3062 ok(swapchain_desc.Windowed,
3063 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
3064 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
3065 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
3066 ok(!swapchain_desc.Flags,
3067 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
3069 IDXGISwapChain_Release(swapchain);
3070 refcount = IDXGIDevice_Release(device);
3071 ok(!refcount, "Device has %u references left.\n", refcount);
3072 DestroyWindow(window);
3075 static void test_swapchain_parameters(void)
3077 DXGI_USAGE usage, expected_usage, broken_usage;
3078 D3D10_TEXTURE2D_DESC d3d10_texture_desc;
3079 D3D11_TEXTURE2D_DESC d3d11_texture_desc;
3080 unsigned int expected_bind_flags;
3081 ID3D10Texture2D *d3d10_texture;
3082 ID3D11Texture2D *d3d11_texture;
3083 DXGI_SWAP_CHAIN_DESC desc;
3084 IDXGISwapChain *swapchain;
3085 IDXGIResource *resource;
3086 IDXGIAdapter *adapter;
3087 IDXGIFactory *factory;
3088 IDXGIDevice *device;
3089 unsigned int i, j;
3090 ULONG refcount;
3091 IUnknown *obj;
3092 HWND window;
3093 HRESULT hr;
3095 static const struct
3097 BOOL windowed;
3098 UINT buffer_count;
3099 DXGI_SWAP_EFFECT swap_effect;
3100 HRESULT hr, vista_hr;
3101 UINT highest_accessible_buffer;
3103 tests[] =
3105 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3106 {TRUE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3107 {TRUE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3108 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3109 {TRUE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
3110 {TRUE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
3111 {TRUE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
3112 {TRUE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3113 {TRUE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3114 {TRUE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3115 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3116 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3117 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
3118 {TRUE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
3119 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3120 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3121 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
3122 {TRUE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3123 {TRUE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3124 {TRUE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3125 {TRUE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3126 {TRUE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
3127 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
3128 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
3129 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3130 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3131 {TRUE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3132 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3134 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3135 {FALSE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3136 {FALSE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3137 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3138 {FALSE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
3139 {FALSE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
3140 {FALSE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
3141 {FALSE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3142 {FALSE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3143 {FALSE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3144 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3145 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3146 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
3147 {FALSE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
3148 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3149 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3150 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
3151 {FALSE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3152 {FALSE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3153 {FALSE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3154 {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
3155 {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
3156 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
3157 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
3158 * process. Disable it for now.
3159 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
3161 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3162 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3163 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3164 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
3166 static const DXGI_USAGE usage_tests[] =
3169 DXGI_USAGE_BACK_BUFFER,
3170 DXGI_USAGE_SHADER_INPUT,
3171 DXGI_USAGE_RENDER_TARGET_OUTPUT,
3172 DXGI_USAGE_DISCARD_ON_PRESENT,
3173 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER,
3174 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_DISCARD_ON_PRESENT,
3175 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_DISCARD_ON_PRESENT,
3176 DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT,
3177 DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_DISCARD_ON_PRESENT,
3180 if (!(device = create_device(0)))
3182 skip("Failed to create device, skipping tests.\n");
3183 return;
3185 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
3186 0, 0, 640, 480, 0, 0, 0, 0);
3188 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
3189 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
3191 hr = IDXGIDevice_GetAdapter(device, &adapter);
3192 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
3194 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
3195 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
3197 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3199 memset(&desc, 0, sizeof(desc));
3200 desc.BufferDesc.Width = registry_mode.dmPelsWidth;
3201 desc.BufferDesc.Height = registry_mode.dmPelsHeight;
3202 desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
3203 desc.SampleDesc.Count = 1;
3204 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
3205 desc.OutputWindow = window;
3207 desc.Windowed = tests[i].windowed;
3208 desc.BufferCount = tests[i].buffer_count;
3209 desc.SwapEffect = tests[i].swap_effect;
3211 hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
3212 ok(hr == tests[i].hr || broken(hr == tests[i].vista_hr)
3213 || (SUCCEEDED(tests[i].hr) && hr == DXGI_STATUS_OCCLUDED),
3214 "Got unexpected hr %#x, test %u.\n", hr, i);
3215 if (FAILED(hr))
3216 continue;
3218 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
3219 todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
3220 if (FAILED(hr))
3222 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
3223 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
3225 IDXGISwapChain_Release(swapchain);
3226 continue;
3229 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
3230 if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
3231 expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
3232 hr = IDXGIResource_GetUsage(resource, &usage);
3233 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
3234 ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
3236 IDXGIResource_Release(resource);
3238 hr = IDXGISwapChain_GetDesc(swapchain, &desc);
3239 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
3241 for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
3243 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
3244 ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
3246 /* Buffers > 0 are supposed to be read only. This is the case except that in
3247 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
3248 * writable. This is not the case if an unsupported refresh rate is passed
3249 * for some reason, probably because the invalid refresh rate triggers a
3250 * kinda-sorta windowed mode.
3252 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
3253 * broken.
3255 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
3256 * the draw on the screen right away (Aero on or off doesn't matter), but
3257 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
3259 * Note that if the application doesn't have focused creating a fullscreen
3260 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
3261 * so use the Windowed property of the swapchain that was actually created. */
3262 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_READ_ONLY;
3263 broken_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
3265 if (desc.Windowed || j < tests[i].highest_accessible_buffer)
3266 broken_usage |= DXGI_USAGE_READ_ONLY;
3268 hr = IDXGIResource_GetUsage(resource, &usage);
3269 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr, i, j);
3270 ok(usage == expected_usage || broken(usage == broken_usage),
3271 "Got usage %x, expected %x, test %u, buffer %u.\n",
3272 usage, expected_usage, i, j);
3274 IDXGIResource_Release(resource);
3276 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
3277 ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
3279 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
3280 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
3282 IDXGISwapChain_Release(swapchain);
3285 for (i = 0; i < ARRAY_SIZE(usage_tests); ++i)
3287 usage = usage_tests[i];
3289 memset(&desc, 0, sizeof(desc));
3290 desc.BufferDesc.Width = registry_mode.dmPelsWidth;
3291 desc.BufferDesc.Height = registry_mode.dmPelsHeight;
3292 desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
3293 desc.SampleDesc.Count = 1;
3294 desc.BufferUsage = usage;
3295 desc.BufferCount = 1;
3296 desc.OutputWindow = window;
3297 desc.Windowed = TRUE;
3298 desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
3299 hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
3300 ok(hr == S_OK, "Got unexpected hr %#x, test %u.\n", hr, i);
3302 hr = IDXGISwapChain_GetDesc(swapchain, &desc);
3303 ok(hr == S_OK, "Failed to get swapchain desc, hr %#x, test %u.\n", hr, i);
3304 todo_wine_if(usage & ~(DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT))
3305 ok(desc.BufferUsage == usage, "Got usage %#x, expected %#x, test %u.\n", desc.BufferUsage, usage, i);
3307 expected_bind_flags = 0;
3308 if (usage & DXGI_USAGE_RENDER_TARGET_OUTPUT)
3309 expected_bind_flags |= D3D11_BIND_RENDER_TARGET;
3310 if (usage & DXGI_USAGE_SHADER_INPUT)
3311 expected_bind_flags |= D3D11_BIND_SHADER_RESOURCE;
3313 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&d3d10_texture);
3314 ok(hr == S_OK, "Failed to get d3d10 texture, hr %#x, test %u.\n", hr, i);
3315 ID3D10Texture2D_GetDesc(d3d10_texture, &d3d10_texture_desc);
3316 ok(d3d10_texture_desc.BindFlags == expected_bind_flags,
3317 "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
3318 d3d10_texture_desc.BindFlags, expected_bind_flags, i);
3319 ID3D10Texture2D_Release(d3d10_texture);
3321 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void **)&d3d11_texture);
3322 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Failed to get d3d11 texture, hr %#x, test %u.\n", hr, i);
3323 if (SUCCEEDED(hr))
3325 ID3D11Texture2D_GetDesc(d3d11_texture, &d3d11_texture_desc);
3326 ok(d3d11_texture_desc.BindFlags == expected_bind_flags,
3327 "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
3328 d3d11_texture_desc.BindFlags, expected_bind_flags, i);
3329 ID3D11Texture2D_Release(d3d11_texture);
3332 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
3333 todo_wine ok(hr == S_OK, "Failed to get buffer, hr %#x, test %u.\n", hr, i);
3334 if (FAILED(hr))
3336 IDXGISwapChain_Release(swapchain);
3337 continue;
3339 expected_usage = usage | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_DISCARD_ON_PRESENT;
3340 hr = IDXGIResource_GetUsage(resource, &usage);
3341 ok(hr == S_OK, "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
3342 ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
3343 IDXGIResource_Release(resource);
3345 IDXGISwapChain_Release(swapchain);
3348 IDXGIFactory_Release(factory);
3349 IDXGIAdapter_Release(adapter);
3350 IUnknown_Release(obj);
3351 refcount = IDXGIDevice_Release(device);
3352 ok(!refcount, "Device has %u references left.\n", refcount);
3353 DestroyWindow(window);
3356 static void test_maximum_frame_latency(void)
3358 IDXGIDevice1 *device1;
3359 IDXGIDevice *device;
3360 UINT max_latency;
3361 ULONG refcount;
3362 HRESULT hr;
3364 if (!(device = create_device(0)))
3366 skip("Failed to create device.\n");
3367 return;
3370 if (SUCCEEDED(IDXGIDevice_QueryInterface(device, &IID_IDXGIDevice1, (void **)&device1)))
3372 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3373 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3374 ok(max_latency == DEFAULT_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3376 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY);
3377 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3378 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3379 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3380 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3382 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY + 1);
3383 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
3384 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3385 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3386 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3388 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, 0);
3389 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3390 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3391 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3392 /* 0 does not reset to the default frame latency on all Windows versions. */
3393 ok(max_latency == DEFAULT_FRAME_LATENCY || broken(!max_latency),
3394 "Got unexpected maximum frame latency %u.\n", max_latency);
3396 IDXGIDevice1_Release(device1);
3398 else
3400 win_skip("IDXGIDevice1 is not implemented.\n");
3403 refcount = IDXGIDevice_Release(device);
3404 ok(!refcount, "Device has %u references left.\n", refcount);
3407 static void test_output_desc(void)
3409 IDXGIAdapter *adapter, *adapter2;
3410 IDXGIOutput *output, *output2;
3411 DXGI_OUTPUT_DESC desc;
3412 IDXGIFactory *factory;
3413 unsigned int i, j;
3414 ULONG refcount;
3415 HRESULT hr;
3417 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
3418 ok(SUCCEEDED(hr), "Failed to create DXGI factory, hr %#x.\n", hr);
3420 for (i = 0; ; ++i)
3422 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter);
3423 if (hr == DXGI_ERROR_NOT_FOUND)
3424 break;
3425 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3427 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter2);
3428 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3429 ok(adapter != adapter2, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter, adapter2);
3430 refcount = get_refcount((IUnknown *)adapter);
3431 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3432 IDXGIAdapter_Release(adapter2);
3434 refcount = get_refcount((IUnknown *)factory);
3435 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3436 refcount = get_refcount((IUnknown *)adapter);
3437 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3439 for (j = 0; ; ++j)
3441 MONITORINFOEXW monitor_info;
3442 BOOL ret;
3444 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output);
3445 if (hr == DXGI_ERROR_NOT_FOUND)
3446 break;
3447 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3449 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output2);
3450 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3451 ok(output != output2, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output, output2);
3452 refcount = get_refcount((IUnknown *)output);
3453 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3454 IDXGIOutput_Release(output2);
3456 refcount = get_refcount((IUnknown *)factory);
3457 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3458 refcount = get_refcount((IUnknown *)adapter);
3459 ok(refcount == 2, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3460 refcount = get_refcount((IUnknown *)output);
3461 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3463 hr = IDXGIOutput_GetDesc(output, &desc);
3464 ok(SUCCEEDED(hr), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j, i, hr);
3466 monitor_info.cbSize = sizeof(monitor_info);
3467 ret = GetMonitorInfoW(desc.Monitor, (MONITORINFO *)&monitor_info);
3468 ok(ret, "Failed to get monitor info.\n");
3469 ok(!lstrcmpW(desc.DeviceName, monitor_info.szDevice), "Got unexpected device name %s, expected %s.\n",
3470 wine_dbgstr_w(desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
3471 ok(EqualRect(&desc.DesktopCoordinates, &monitor_info.rcMonitor),
3472 "Got unexpected desktop coordinates %s, expected %s.\n",
3473 wine_dbgstr_rect(&desc.DesktopCoordinates),
3474 wine_dbgstr_rect(&monitor_info.rcMonitor));
3476 IDXGIOutput_Release(output);
3477 refcount = get_refcount((IUnknown *)adapter);
3478 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3481 IDXGIAdapter_Release(adapter);
3482 refcount = get_refcount((IUnknown *)factory);
3483 ok(refcount == 1, "Get unexpected refcount %u.\n", refcount);
3486 refcount = IDXGIFactory_Release(factory);
3487 ok(!refcount, "IDXGIFactory has %u references left.\n", refcount);
3490 struct dxgi_adapter
3492 IDXGIAdapter IDXGIAdapter_iface;
3493 IDXGIAdapter *wrapped_iface;
3496 static inline struct dxgi_adapter *impl_from_IDXGIAdapter(IDXGIAdapter *iface)
3498 return CONTAINING_RECORD(iface, struct dxgi_adapter, IDXGIAdapter_iface);
3501 static HRESULT STDMETHODCALLTYPE dxgi_adapter_QueryInterface(IDXGIAdapter *iface, REFIID iid, void **out)
3503 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3505 if (IsEqualGUID(iid, &IID_IDXGIAdapter)
3506 || IsEqualGUID(iid, &IID_IDXGIObject)
3507 || IsEqualGUID(iid, &IID_IUnknown))
3509 IDXGIAdapter_AddRef(adapter->wrapped_iface);
3510 *out = iface;
3511 return S_OK;
3513 return IDXGIAdapter_QueryInterface(adapter->wrapped_iface, iid, out);
3516 static ULONG STDMETHODCALLTYPE dxgi_adapter_AddRef(IDXGIAdapter *iface)
3518 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3519 return IDXGIAdapter_AddRef(adapter->wrapped_iface);
3522 static ULONG STDMETHODCALLTYPE dxgi_adapter_Release(IDXGIAdapter *iface)
3524 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3525 return IDXGIAdapter_Release(adapter->wrapped_iface);
3528 static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetPrivateData(IDXGIAdapter *iface,
3529 REFGUID guid, UINT data_size, const void *data)
3531 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3532 return IDXGIAdapter_SetPrivateData(adapter->wrapped_iface, guid, data_size, data);
3535 static HRESULT STDMETHODCALLTYPE dxgi_adapter_SetPrivateDataInterface(IDXGIAdapter *iface,
3536 REFGUID guid, const IUnknown *object)
3538 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3539 return IDXGIAdapter_SetPrivateDataInterface(adapter->wrapped_iface, guid, object);
3542 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetPrivateData(IDXGIAdapter *iface,
3543 REFGUID guid, UINT *data_size, void *data)
3545 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3546 return IDXGIAdapter_GetPrivateData(adapter->wrapped_iface, guid, data_size, data);
3549 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetParent(IDXGIAdapter *iface, REFIID iid, void **parent)
3551 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3552 return IDXGIAdapter_GetParent(adapter->wrapped_iface, iid, parent);
3555 static HRESULT STDMETHODCALLTYPE dxgi_adapter_EnumOutputs(IDXGIAdapter *iface,
3556 UINT output_idx, IDXGIOutput **output)
3558 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3559 return IDXGIAdapter_EnumOutputs(adapter->wrapped_iface, output_idx, output);
3562 static HRESULT STDMETHODCALLTYPE dxgi_adapter_GetDesc(IDXGIAdapter *iface, DXGI_ADAPTER_DESC *desc)
3564 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3565 return IDXGIAdapter_GetDesc(adapter->wrapped_iface, desc);
3568 static HRESULT STDMETHODCALLTYPE dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter *iface,
3569 REFGUID guid, LARGE_INTEGER *umd_version)
3571 struct dxgi_adapter *adapter = impl_from_IDXGIAdapter(iface);
3572 return IDXGIAdapter_CheckInterfaceSupport(adapter->wrapped_iface, guid, umd_version);
3575 static const struct IDXGIAdapterVtbl dxgi_adapter_vtbl =
3577 dxgi_adapter_QueryInterface,
3578 dxgi_adapter_AddRef,
3579 dxgi_adapter_Release,
3580 dxgi_adapter_SetPrivateData,
3581 dxgi_adapter_SetPrivateDataInterface,
3582 dxgi_adapter_GetPrivateData,
3583 dxgi_adapter_GetParent,
3584 dxgi_adapter_EnumOutputs,
3585 dxgi_adapter_GetDesc,
3586 dxgi_adapter_CheckInterfaceSupport,
3589 static void test_object_wrapping(void)
3591 struct dxgi_adapter wrapper;
3592 DXGI_ADAPTER_DESC desc;
3593 IDXGIAdapter *adapter;
3594 IDXGIFactory *factory;
3595 ID3D10Device1 *device;
3596 ULONG refcount;
3597 HRESULT hr;
3599 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
3600 ok(hr == S_OK, "Failed to create DXGI factory, hr %#x.\n", hr);
3602 hr = IDXGIFactory_EnumAdapters(factory, 0, &adapter);
3603 if (hr == DXGI_ERROR_NOT_FOUND)
3605 skip("Could not enumerate adapters.\n");
3606 IDXGIFactory_Release(factory);
3607 return;
3609 ok(hr == S_OK, "Failed to enumerate adapter, hr %#x.\n", hr);
3611 wrapper.IDXGIAdapter_iface.lpVtbl = &dxgi_adapter_vtbl;
3612 wrapper.wrapped_iface = adapter;
3614 hr = D3D10CreateDevice1(&wrapper.IDXGIAdapter_iface, D3D10_DRIVER_TYPE_HARDWARE, NULL,
3615 0, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device);
3616 if (SUCCEEDED(hr))
3618 refcount = ID3D10Device1_Release(device);
3619 ok(!refcount, "Device has %u references left.\n", refcount);
3622 hr = IDXGIAdapter_GetDesc(&wrapper.IDXGIAdapter_iface, &desc);
3623 ok(hr == S_OK, "Failed to get adapter desc, hr %#x.\n", hr);
3625 refcount = IDXGIAdapter_Release(&wrapper.IDXGIAdapter_iface);
3626 ok(!refcount, "Adapter has %u references left.\n", refcount);
3627 refcount = IDXGIFactory_Release(factory);
3628 ok(!refcount, "Factory has %u references left.\n", refcount);
3631 START_TEST(device)
3633 HMODULE dxgi_module = GetModuleHandleA("dxgi.dll");
3634 pCreateDXGIFactory1 = (void *)GetProcAddress(dxgi_module, "CreateDXGIFactory1");
3635 pCreateDXGIFactory2 = (void *)GetProcAddress(dxgi_module, "CreateDXGIFactory2");
3637 registry_mode.dmSize = sizeof(registry_mode);
3638 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
3640 test_adapter_desc();
3641 test_adapter_luid();
3642 test_check_interface_support();
3643 test_create_surface();
3644 test_parents();
3645 test_output();
3646 test_find_closest_matching_mode();
3647 test_create_swapchain();
3648 test_get_containing_output();
3649 test_set_fullscreen();
3650 test_default_fullscreen_target_output();
3651 test_resize_target();
3652 test_inexact_modes();
3653 test_create_factory();
3654 test_private_data();
3655 test_swapchain_resize();
3656 test_swapchain_parameters();
3657 test_maximum_frame_latency();
3658 test_output_desc();
3659 test_object_wrapping();