dxgi: Added support for DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE.
[wine.git] / dlls / dxgi / tests / device.c
blob2bc0ff4071bc8f7b6004ae152439729f7676c9e4
1 /*
2 * Copyright 2008 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <assert.h>
20 #define COBJMACROS
21 #include "initguid.h"
22 #include "d3d11.h"
23 #include "wine/test.h"
25 enum frame_latency
27 DEFAULT_FRAME_LATENCY = 3,
28 MAX_FRAME_LATENCY = 16,
31 static DEVMODEW registry_mode;
33 static HRESULT (WINAPI *pCreateDXGIFactory1)(REFIID iid, void **factory);
35 static ULONG get_refcount(IUnknown *iface)
37 IUnknown_AddRef(iface);
38 return IUnknown_Release(iface);
41 #define MODE_DESC_IGNORE_RESOLUTION 0x00000001u
42 #define MODE_DESC_IGNORE_REFRESH_RATE 0x00000002u
43 #define MODE_DESC_IGNORE_FORMAT 0x00000004u
44 #define MODE_DESC_IGNORE_SCANLINE_ORDERING 0x00000008u
45 #define MODE_DESC_IGNORE_SCALING 0x00000010u
47 #define MODE_DESC_CHECK_RESOLUTION (~MODE_DESC_IGNORE_RESOLUTION)
48 #define MODE_DESC_CHECK_FORMAT (~MODE_DESC_IGNORE_FORMAT)
50 #define check_mode_desc(a, b, c) check_mode_desc_(__LINE__, a, b, c)
51 static void check_mode_desc_(unsigned int line, const DXGI_MODE_DESC *desc,
52 const DXGI_MODE_DESC *expected_desc, unsigned int ignore_flags)
54 if (!(ignore_flags & MODE_DESC_IGNORE_RESOLUTION))
56 ok_(__FILE__, line)(desc->Width == expected_desc->Width
57 && desc->Height == expected_desc->Height,
58 "Got resolution %ux%u, expected %ux%u.\n",
59 desc->Width, desc->Height, expected_desc->Width, expected_desc->Height);
61 if (!(ignore_flags & MODE_DESC_IGNORE_REFRESH_RATE))
63 ok_(__FILE__, line)(desc->RefreshRate.Numerator == expected_desc->RefreshRate.Numerator
64 && desc->RefreshRate.Denominator == expected_desc->RefreshRate.Denominator,
65 "Got refresh rate %u / %u, expected %u / %u.\n",
66 desc->RefreshRate.Numerator, desc->RefreshRate.Denominator,
67 expected_desc->RefreshRate.Denominator, expected_desc->RefreshRate.Denominator);
69 if (!(ignore_flags & MODE_DESC_IGNORE_FORMAT))
71 ok_(__FILE__, line)(desc->Format == expected_desc->Format,
72 "Got format %#x, expected %#x.\n", desc->Format, expected_desc->Format);
74 if (!(ignore_flags & MODE_DESC_IGNORE_SCANLINE_ORDERING))
76 ok_(__FILE__, line)(desc->ScanlineOrdering == expected_desc->ScanlineOrdering,
77 "Got scanline ordering %#x, expected %#x.\n",
78 desc->ScanlineOrdering, expected_desc->ScanlineOrdering);
80 if (!(ignore_flags & MODE_DESC_IGNORE_SCALING))
82 ok_(__FILE__, line)(desc->Scaling == expected_desc->Scaling,
83 "Got scaling %#x, expected %#x.\n",
84 desc->Scaling, expected_desc->Scaling);
88 #define check_output_desc(a, b) check_output_desc_(__LINE__, a, b)
89 static void check_output_desc_(unsigned int line, const DXGI_OUTPUT_DESC *desc,
90 const struct DXGI_OUTPUT_DESC *expected_desc)
92 ok_(__FILE__, line)(!lstrcmpW(desc->DeviceName, expected_desc->DeviceName),
93 "Got unexpected device name %s, expected %s.\n",
94 wine_dbgstr_w(desc->DeviceName), wine_dbgstr_w(expected_desc->DeviceName));
95 ok_(__FILE__, line)(EqualRect(&desc->DesktopCoordinates, &expected_desc->DesktopCoordinates),
96 "Got unexpected desktop coordinates %s, expected %s.\n",
97 wine_dbgstr_rect(&desc->DesktopCoordinates),
98 wine_dbgstr_rect(&expected_desc->DesktopCoordinates));
101 #define check_output_equal(a, b) check_output_equal_(__LINE__, a, b)
102 static void check_output_equal_(unsigned int line, IDXGIOutput *output1, IDXGIOutput *output2)
104 DXGI_OUTPUT_DESC desc1, desc2;
105 HRESULT hr;
107 hr = IDXGIOutput_GetDesc(output1, &desc1);
108 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
109 hr = IDXGIOutput_GetDesc(output2, &desc2);
110 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
111 check_output_desc_(line, &desc1, &desc2);
114 static BOOL output_belongs_to_adapter(IDXGIOutput *output, IDXGIAdapter *adapter)
116 DXGI_OUTPUT_DESC output_desc, desc;
117 unsigned int output_idx;
118 IDXGIOutput *o;
119 HRESULT hr;
121 hr = IDXGIOutput_GetDesc(output, &output_desc);
122 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
124 for (output_idx = 0; IDXGIAdapter_EnumOutputs(adapter, output_idx, &o) != DXGI_ERROR_NOT_FOUND; ++output_idx)
126 hr = IDXGIOutput_GetDesc(o, &desc);
127 ok(SUCCEEDED(hr), "Failed to get output desc, hr %#x.\n", hr);
128 IDXGIOutput_Release(o);
130 if (!lstrcmpW(desc.DeviceName, output_desc.DeviceName)
131 && EqualRect(&desc.DesktopCoordinates, &output_desc.DesktopCoordinates))
132 return TRUE;
135 return FALSE;
138 struct fullscreen_state
140 RECT window_rect;
141 RECT client_rect;
142 HMONITOR monitor;
143 RECT monitor_rect;
146 struct swapchain_fullscreen_state
148 struct fullscreen_state fullscreen_state;
149 BOOL fullscreen;
150 IDXGIOutput *target;
153 #define capture_fullscreen_state(a, b) capture_fullscreen_state_(__LINE__, a, b)
154 static void capture_fullscreen_state_(unsigned int line, struct fullscreen_state *state, HWND window)
156 MONITORINFOEXW monitor_info;
157 BOOL ret;
159 ret = GetWindowRect(window, &state->window_rect);
160 ok_(__FILE__, line)(ret, "GetWindowRect failed.\n");
161 ret = GetClientRect(window, &state->client_rect);
162 ok_(__FILE__, line)(ret, "GetClientRect failed.\n");
164 state->monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
165 ok_(__FILE__, line)(!!state->monitor, "Failed to get monitor from window.\n");
167 monitor_info.cbSize = sizeof(monitor_info);
168 ret = GetMonitorInfoW(state->monitor, (MONITORINFO *)&monitor_info);
169 ok_(__FILE__, line)(ret, "Failed to get monitor info.\n");
170 state->monitor_rect = monitor_info.rcMonitor;
173 #define check_fullscreen_state(a, b) check_fullscreen_state_(__LINE__, a, b)
174 static void check_fullscreen_state_(unsigned int line, const struct fullscreen_state *state,
175 const struct fullscreen_state *expected_state)
177 ok_(__FILE__, line)(EqualRect(&state->window_rect, &expected_state->window_rect),
178 "Got window rect %s, expected %s.\n",
179 wine_dbgstr_rect(&state->window_rect), wine_dbgstr_rect(&expected_state->window_rect));
180 ok_(__FILE__, line)(EqualRect(&state->client_rect, &expected_state->client_rect),
181 "Got client rect %s, expected %s.\n",
182 wine_dbgstr_rect(&state->client_rect), wine_dbgstr_rect(&expected_state->client_rect));
183 ok_(__FILE__, line)(state->monitor == expected_state->monitor,
184 "Got monitor %p, expected %p.\n",
185 state->monitor, expected_state->monitor);
186 ok_(__FILE__, line)(EqualRect(&state->monitor_rect, &expected_state->monitor_rect),
187 "Got monitor rect %s, expected %s.\n",
188 wine_dbgstr_rect(&state->monitor_rect), wine_dbgstr_rect(&expected_state->monitor_rect));
191 #define check_window_fullscreen_state(a, b) check_window_fullscreen_state_(__LINE__, a, b)
192 static void check_window_fullscreen_state_(unsigned int line, HWND window,
193 const struct fullscreen_state *expected_state)
195 struct fullscreen_state current_state;
196 capture_fullscreen_state_(line, &current_state, window);
197 check_fullscreen_state_(line, &current_state, expected_state);
200 #define check_swapchain_fullscreen_state(a, b) check_swapchain_fullscreen_state_(__LINE__, a, b)
201 static void check_swapchain_fullscreen_state_(unsigned int line, IDXGISwapChain *swapchain,
202 const struct swapchain_fullscreen_state *expected_state)
204 IDXGIOutput *containing_output, *target;
205 DXGI_SWAP_CHAIN_DESC swapchain_desc;
206 BOOL fullscreen;
207 HRESULT hr;
209 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
210 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
211 check_window_fullscreen_state_(line, swapchain_desc.OutputWindow, &expected_state->fullscreen_state);
213 ok_(__FILE__, line)(swapchain_desc.Windowed == !expected_state->fullscreen,
214 "Got windowed %#x, expected %#x.\n",
215 swapchain_desc.Windowed, !expected_state->fullscreen);
217 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
218 ok_(__FILE__, line)(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
219 ok_(__FILE__, line)(fullscreen == expected_state->fullscreen, "Got fullscreen %#x, expected %#x.\n",
220 fullscreen, expected_state->fullscreen);
222 if (!swapchain_desc.Windowed && expected_state->fullscreen)
224 IDXGIAdapter *adapter;
225 IDXGIDevice *device;
227 hr = IDXGISwapChain_GetDevice(swapchain, &IID_IDXGIDevice, (void **)&device);
228 ok_(__FILE__, line)(SUCCEEDED(hr), "GetDevice failed, hr %#x.\n", hr);
229 hr = IDXGIDevice_GetAdapter(device, &adapter);
230 ok_(__FILE__, line)(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
231 IDXGIDevice_Release(device);
233 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
234 ok_(__FILE__, line)(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
236 check_output_equal_(line, target, expected_state->target);
237 ok_(__FILE__, line)(target == containing_output, "Got target %p, expected %p.\n",
238 target, containing_output);
239 ok_(__FILE__, line)(output_belongs_to_adapter(target, adapter),
240 "Output %p doesn't belong to adapter %p.\n",
241 target, adapter);
243 IDXGIOutput_Release(target);
244 IDXGIOutput_Release(containing_output);
245 IDXGIAdapter_Release(adapter);
247 else
249 ok_(__FILE__, line)(!target, "Got unexpected target %p.\n", target);
253 #define compute_expected_swapchain_fullscreen_state_after_fullscreen_change(a, b, c, d, e, f) \
254 compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(__LINE__, a, b, c, d, e, f)
255 static void compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(unsigned int line,
256 struct swapchain_fullscreen_state *state, const DXGI_SWAP_CHAIN_DESC *swapchain_desc,
257 const RECT *old_monitor_rect, unsigned int new_width, unsigned int new_height, IDXGIOutput *target)
259 if (!new_width && !new_height)
261 RECT client_rect;
262 GetClientRect(swapchain_desc->OutputWindow, &client_rect);
263 new_width = client_rect.right - client_rect.left;
264 new_height = client_rect.bottom - client_rect.top;
267 if (target)
269 DXGI_MODE_DESC mode_desc = swapchain_desc->BufferDesc;
270 HRESULT hr;
272 mode_desc.Width = new_width;
273 mode_desc.Height = new_height;
274 hr = IDXGIOutput_FindClosestMatchingMode(target, &mode_desc, &mode_desc, NULL);
275 ok_(__FILE__, line)(SUCCEEDED(hr), "FindClosestMatchingMode failed, hr %#x.\n", hr);
276 new_width = mode_desc.Width;
277 new_height = mode_desc.Height;
280 state->fullscreen = TRUE;
281 if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
283 unsigned int new_x = (old_monitor_rect->left >= 0)
284 ? old_monitor_rect->left : old_monitor_rect->right - new_width;
285 unsigned new_y = (old_monitor_rect->top >= 0)
286 ? old_monitor_rect->top : old_monitor_rect->bottom - new_height;
287 RECT new_monitor_rect = {0, 0, new_width, new_height};
288 OffsetRect(&new_monitor_rect, new_x, new_y);
290 SetRect(&state->fullscreen_state.client_rect, 0, 0, new_width, new_height);
291 state->fullscreen_state.monitor_rect = new_monitor_rect;
292 state->fullscreen_state.window_rect = new_monitor_rect;
294 if (target)
295 state->target = target;
297 else
299 state->fullscreen_state.window_rect = *old_monitor_rect;
300 SetRect(&state->fullscreen_state.client_rect, 0, 0,
301 old_monitor_rect->right - old_monitor_rect->left,
302 old_monitor_rect->bottom - old_monitor_rect->top);
306 static IDXGIDevice *create_device(UINT flags)
308 IDXGIDevice *dxgi_device;
309 ID3D10Device1 *device;
310 HRESULT hr;
312 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL,
313 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
314 goto success;
315 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_WARP, NULL,
316 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
317 goto success;
318 if (SUCCEEDED(D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_REFERENCE, NULL,
319 flags, D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &device)))
320 goto success;
322 return NULL;
324 success:
325 hr = ID3D10Device1_QueryInterface(device, &IID_IDXGIDevice, (void **)&dxgi_device);
326 ok(SUCCEEDED(hr), "Created device does not implement IDXGIDevice\n");
327 ID3D10Device1_Release(device);
329 return dxgi_device;
332 static void test_adapter_desc(void)
334 DXGI_ADAPTER_DESC1 desc1;
335 IDXGIAdapter1 *adapter1;
336 DXGI_ADAPTER_DESC desc;
337 IDXGIAdapter *adapter;
338 IDXGIDevice *device;
339 ULONG refcount;
340 HRESULT hr;
342 if (!(device = create_device(0)))
344 skip("Failed to create device, skipping tests.\n");
345 return;
348 hr = IDXGIDevice_GetAdapter(device, &adapter);
349 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
351 hr = IDXGIAdapter_GetDesc(adapter, NULL);
352 ok(hr == E_INVALIDARG, "GetDesc returned %#x, expected %#x.\n",
353 hr, E_INVALIDARG);
355 hr = IDXGIAdapter_GetDesc(adapter, &desc);
356 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
358 trace("%s.\n", wine_dbgstr_w(desc.Description));
359 trace("%04x: %04x:%04x (rev %02x).\n",
360 desc.SubSysId, desc.VendorId, desc.DeviceId, desc.Revision);
361 trace("Dedicated video memory: %lu (%lu MB).\n",
362 desc.DedicatedVideoMemory, desc.DedicatedVideoMemory / (1024 * 1024));
363 trace("Dedicated system memory: %lu (%lu MB).\n",
364 desc.DedicatedSystemMemory, desc.DedicatedSystemMemory / (1024 * 1024));
365 trace("Shared system memory: %lu (%lu MB).\n",
366 desc.SharedSystemMemory, desc.SharedSystemMemory / (1024 * 1024));
367 trace("LUID: %08x:%08x.\n", desc.AdapterLuid.HighPart, desc.AdapterLuid.LowPart);
369 hr = IDXGIAdapter_QueryInterface(adapter, &IID_IDXGIAdapter1, (void **)&adapter1);
370 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE), "Got unexpected hr %#x.\n", hr);
371 if (hr == E_NOINTERFACE)
372 goto done;
374 hr = IDXGIAdapter1_GetDesc1(adapter1, &desc1);
375 ok(SUCCEEDED(hr), "GetDesc1 failed, hr %#x.\n", hr);
377 ok(!lstrcmpW(desc.Description, desc1.Description),
378 "Got unexpected description %s.\n", wine_dbgstr_w(desc1.Description));
379 ok(desc1.VendorId == desc.VendorId, "Got unexpected vendor ID %04x.\n", desc1.VendorId);
380 ok(desc1.DeviceId == desc.DeviceId, "Got unexpected device ID %04x.\n", desc1.DeviceId);
381 ok(desc1.SubSysId == desc.SubSysId, "Got unexpected sub system ID %04x.\n", desc1.SubSysId);
382 ok(desc1.Revision == desc.Revision, "Got unexpected revision %02x.\n", desc1.Revision);
383 ok(desc1.DedicatedVideoMemory == desc.DedicatedVideoMemory,
384 "Got unexpected dedicated video memory %lu.\n", desc1.DedicatedVideoMemory);
385 ok(desc1.DedicatedSystemMemory == desc.DedicatedSystemMemory,
386 "Got unexpected dedicated system memory %lu.\n", desc1.DedicatedSystemMemory);
387 ok(desc1.SharedSystemMemory == desc.SharedSystemMemory,
388 "Got unexpected shared system memory %lu.\n", desc1.SharedSystemMemory);
389 ok(!memcmp(&desc.AdapterLuid, &desc1.AdapterLuid, sizeof(desc.AdapterLuid)),
390 "Got unexpected adapter LUID %08x:%08x.\n", desc1.AdapterLuid.HighPart, desc1.AdapterLuid.LowPart);
391 trace("Flags: %08x.\n", desc1.Flags);
393 IDXGIAdapter1_Release(adapter1);
395 done:
396 IDXGIAdapter_Release(adapter);
397 refcount = IDXGIDevice_Release(device);
398 ok(!refcount, "Device has %u references left.\n", refcount);
401 static void test_check_interface_support(void)
403 LARGE_INTEGER driver_version;
404 IDXGIAdapter *adapter;
405 IDXGIDevice *device;
406 IUnknown *iface;
407 ULONG refcount;
408 HRESULT hr;
410 if (!(device = create_device(0)))
412 skip("Failed to create device.\n");
413 return;
416 hr = IDXGIDevice_GetAdapter(device, &adapter);
417 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
419 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, NULL);
420 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
421 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device, &driver_version);
422 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
424 trace("UMD version: %u.%u.%u.%u.\n",
425 HIWORD(U(driver_version).HighPart), LOWORD(U(driver_version).HighPart),
426 HIWORD(U(driver_version).LowPart), LOWORD(U(driver_version).LowPart));
428 hr = IDXGIDevice_QueryInterface(device, &IID_ID3D10Device1, (void **)&iface);
429 if (SUCCEEDED(hr))
431 IUnknown_Release(iface);
432 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, NULL);
433 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
434 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D10Device1, &driver_version);
435 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
437 else
439 win_skip("D3D10.1 is not supported.\n");
442 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, NULL);
443 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
444 driver_version.HighPart = driver_version.LowPart = 0xdeadbeef;
445 hr = IDXGIAdapter_CheckInterfaceSupport(adapter, &IID_ID3D11Device, &driver_version);
446 ok(hr == DXGI_ERROR_UNSUPPORTED, "Got unexpected hr %#x.\n", hr);
447 ok(driver_version.HighPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.HighPart);
448 ok(driver_version.LowPart == 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version.LowPart);
450 IDXGIAdapter_Release(adapter);
451 refcount = IDXGIDevice_Release(device);
452 ok(!refcount, "Device has %u references left.\n", refcount);
455 static void test_create_surface(void)
457 DXGI_SURFACE_DESC desc;
458 IDXGISurface *surface;
459 IDXGIDevice *device;
460 IUnknown *surface1;
461 IUnknown *texture;
462 ULONG refcount;
463 HRESULT hr;
465 if (!(device = create_device(0)))
467 skip("Failed to create device, skipping tests.\n");
468 return;
471 desc.Width = 512;
472 desc.Height = 512;
473 desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
474 desc.SampleDesc.Count = 1;
475 desc.SampleDesc.Quality = 0;
477 hr = IDXGIDevice_CreateSurface(device, &desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
478 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
480 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D10Texture2D, (void **)&texture);
481 ok(SUCCEEDED(hr), "Surface should implement ID3D10Texture2D\n");
482 IUnknown_Release(texture);
484 hr = IDXGISurface_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture);
485 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
486 "Surface should implement ID3D11Texture2D.\n");
487 if (SUCCEEDED(hr)) IUnknown_Release(texture);
489 hr = IDXGISurface_QueryInterface(surface, &IID_IDXGISurface1, (void **)&surface1);
490 ok(SUCCEEDED(hr) || broken(hr == E_NOINTERFACE) /* Not available on all Windows versions. */,
491 "Surface should implement IDXGISurface1.\n");
492 if (SUCCEEDED(hr)) IUnknown_Release(surface1);
494 IDXGISurface_Release(surface);
495 refcount = IDXGIDevice_Release(device);
496 ok(!refcount, "Device has %u references left.\n", refcount);
499 static void test_parents(void)
501 DXGI_SURFACE_DESC surface_desc;
502 IDXGISurface *surface;
503 IDXGIFactory *factory;
504 IDXGIAdapter *adapter;
505 IDXGIDevice *device;
506 IDXGIOutput *output;
507 IUnknown *parent;
508 ULONG refcount;
509 HRESULT hr;
511 if (!(device = create_device(0)))
513 skip("Failed to create device, skipping tests.\n");
514 return;
517 surface_desc.Width = 512;
518 surface_desc.Height = 512;
519 surface_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
520 surface_desc.SampleDesc.Count = 1;
521 surface_desc.SampleDesc.Quality = 0;
523 hr = IDXGIDevice_CreateSurface(device, &surface_desc, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT, NULL, &surface);
524 ok(SUCCEEDED(hr), "Failed to create a dxgi surface, hr %#x\n", hr);
526 hr = IDXGISurface_GetParent(surface, &IID_IDXGIDevice, (void **)&parent);
527 IDXGISurface_Release(surface);
528 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
529 ok(parent == (IUnknown *)device, "Got parent %p, expected %p.\n", parent, device);
530 IUnknown_Release(parent);
532 hr = IDXGIDevice_GetAdapter(device, &adapter);
533 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
535 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
536 if (hr == DXGI_ERROR_NOT_FOUND)
538 skip("Adapter has not outputs, skipping output tests.\n");
540 else
542 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
544 hr = IDXGIOutput_GetParent(output, &IID_IDXGIAdapter, (void **)&parent);
545 IDXGIOutput_Release(output);
546 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
547 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
548 IUnknown_Release(parent);
551 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
552 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
554 hr = IDXGIFactory_GetParent(factory, &IID_IUnknown, (void **)&parent);
555 ok(hr == E_NOINTERFACE, "GetParent returned %#x, expected %#x.\n", hr, E_NOINTERFACE);
556 ok(parent == NULL, "Got parent %p, expected %p.\n", parent, NULL);
557 IDXGIFactory_Release(factory);
559 hr = IDXGIDevice_GetParent(device, &IID_IDXGIAdapter, (void **)&parent);
560 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
561 ok(parent == (IUnknown *)adapter, "Got parent %p, expected %p.\n", parent, adapter);
562 IUnknown_Release(parent);
564 IDXGIAdapter_Release(adapter);
565 refcount = IDXGIDevice_Release(device);
566 ok(!refcount, "Device has %u references left.\n", refcount);
569 static void test_output(void)
571 IDXGIAdapter *adapter;
572 IDXGIDevice *device;
573 HRESULT hr;
574 IDXGIOutput *output;
575 ULONG refcount;
576 UINT mode_count, mode_count_comp, i;
577 DXGI_MODE_DESC *modes;
579 if (!(device = create_device(0)))
581 skip("Failed to create device, skipping tests.\n");
582 return;
585 hr = IDXGIDevice_GetAdapter(device, &adapter);
586 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
588 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
589 if (hr == DXGI_ERROR_NOT_FOUND)
591 skip("Adapter doesn't have any outputs, skipping tests.\n");
592 IDXGIAdapter_Release(adapter);
593 IDXGIDevice_Release(device);
594 return;
596 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
598 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NULL, NULL);
599 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
601 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
602 ok(SUCCEEDED(hr)
603 || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Remote Desktop Services / Win 7 testbot */
604 "Failed to list modes, hr %#x.\n", hr);
605 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
607 win_skip("GetDisplayModeList() not supported.\n");
608 IDXGIOutput_Release(output);
609 IDXGIAdapter_Release(adapter);
610 IDXGIDevice_Release(device);
611 return;
613 mode_count_comp = mode_count;
615 hr = IDXGIOutput_GetDisplayModeList(output, 0, 0, &mode_count, NULL);
616 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
617 ok(!mode_count, "Got unexpected mode_count %u.\n", mode_count);
619 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
620 DXGI_ENUM_MODES_SCALING, &mode_count, NULL);
621 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
622 ok(mode_count >= mode_count_comp, "Got unexpected mode_count %u, expected >= %u.\n", mode_count, mode_count_comp);
623 mode_count_comp = mode_count;
625 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * (mode_count + 10));
627 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
628 DXGI_ENUM_MODES_SCALING, NULL, modes);
629 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
630 ok(!modes[0].Height, "No output was expected.\n");
632 mode_count = 0;
633 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
634 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
635 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
636 ok(!modes[0].Height, "No output was expected.\n");
638 mode_count = mode_count_comp;
639 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
640 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
641 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
642 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
644 for (i = 0; i < mode_count; i++)
646 ok(modes[i].Height && modes[i].Width, "Proper mode was expected\n");
649 mode_count += 5;
650 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
651 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
652 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
653 ok(mode_count == mode_count_comp, "Got unexpected mode_count %u, expected %u.\n", mode_count, mode_count_comp);
655 if (mode_count_comp)
657 mode_count = mode_count_comp - 1;
658 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM,
659 DXGI_ENUM_MODES_SCALING, &mode_count, modes);
660 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
661 ok(mode_count == mode_count_comp - 1, "Got unexpected mode_count %u, expected %u.\n",
662 mode_count, mode_count_comp - 1);
664 else
666 skip("Not enough modes for test, skipping.\n");
669 HeapFree(GetProcessHeap(), 0, modes);
670 IDXGIOutput_Release(output);
671 IDXGIAdapter_Release(adapter);
672 refcount = IDXGIDevice_Release(device);
673 ok(!refcount, "Device has %u references left.\n", refcount);
676 static void test_find_closest_matching_mode(void)
678 DXGI_MODE_DESC *modes, mode, matching_mode;
679 unsigned int i, mode_count;
680 IDXGIAdapter *adapter;
681 IDXGIDevice *device;
682 IDXGIOutput *output;
683 ULONG refcount;
684 HRESULT hr;
686 if (!(device = create_device(0)))
688 skip("Failed to create device.\n");
689 return;
692 hr = IDXGIDevice_GetAdapter(device, &adapter);
693 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
695 hr = IDXGIAdapter_EnumOutputs(adapter, 0, &output);
696 if (hr == DXGI_ERROR_NOT_FOUND)
698 win_skip("Adapter doesn't have any outputs.\n");
699 IDXGIAdapter_Release(adapter);
700 IDXGIDevice_Release(device);
701 return;
703 ok(SUCCEEDED(hr), "EnumOutputs failed, hr %#x.\n", hr);
705 memset(&mode, 0, sizeof(mode));
706 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
707 ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
708 "Got unexpected hr %#x.\n", hr);
709 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
711 win_skip("FindClosestMatchingMode() not supported.\n");
712 goto done;
715 memset(&mode, 0, sizeof(mode));
716 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, (IUnknown *)device);
717 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
719 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
720 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
722 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
724 hr = IDXGIOutput_GetDisplayModeList(output, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
725 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
727 for (i = 0; i < mode_count; ++i)
729 mode = modes[i];
730 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
731 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
732 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING);
734 mode.Format = DXGI_FORMAT_UNKNOWN;
735 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
736 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
738 mode = modes[i];
739 mode.Width = 0;
740 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
741 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
743 mode = modes[i];
744 mode.Height = 0;
745 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
746 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
748 mode = modes[i];
749 mode.Width = mode.Height = 0;
750 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
751 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
752 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_RESOLUTION);
753 ok(matching_mode.Width > 0 && matching_mode.Height > 0, "Got unexpected resolution %ux%u.\n",
754 matching_mode.Width, matching_mode.Height);
756 mode = modes[i];
757 mode.RefreshRate.Numerator = mode.RefreshRate.Denominator = 0;
758 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
759 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
760 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_REFRESH_RATE);
761 ok(matching_mode.RefreshRate.Numerator > 0 && matching_mode.RefreshRate.Denominator > 0,
762 "Got unexpected refresh rate %u / %u.\n",
763 matching_mode.RefreshRate.Numerator, matching_mode.RefreshRate.Denominator);
765 mode = modes[i];
766 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
767 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
768 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
769 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_IGNORE_SCALING | MODE_DESC_IGNORE_SCANLINE_ORDERING);
770 ok(matching_mode.ScanlineOrdering, "Got unexpected scanline ordering %#x.\n",
771 matching_mode.ScanlineOrdering);
773 memset(&mode, 0, sizeof(mode));
774 mode.Width = modes[i].Width;
775 mode.Height = modes[i].Height;
776 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
777 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
778 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
779 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
781 memset(&mode, 0, sizeof(mode));
782 mode.Width = modes[i].Width - 1;
783 mode.Height = modes[i].Height - 1;
784 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
785 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
786 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
787 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
789 memset(&mode, 0, sizeof(mode));
790 mode.Width = modes[i].Width + 1;
791 mode.Height = modes[i].Height + 1;
792 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
793 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
794 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
795 check_mode_desc(&matching_mode, &modes[i], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
798 memset(&mode, 0, sizeof(mode));
799 mode.Width = mode.Height = 10;
800 mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
801 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
802 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
803 /* Find mode for the lowest resolution. */
804 mode = modes[0];
805 for (i = 0; i < mode_count; ++i)
807 if (mode.Width >= modes[i].Width && mode.Height >= modes[i].Height)
808 mode = modes[i];
810 check_mode_desc(&matching_mode, &mode, MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
812 memset(&mode, 0, sizeof(mode));
813 mode.Width = modes[0].Width;
814 mode.Height = modes[0].Height;
815 mode.Format = modes[0].Format;
816 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST;
817 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
818 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
819 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
821 memset(&mode, 0, sizeof(mode));
822 mode.Width = modes[0].Width;
823 mode.Height = modes[0].Height;
824 mode.Format = modes[0].Format;
825 mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST;
826 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
827 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
828 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
830 memset(&mode, 0, sizeof(mode));
831 mode.Width = modes[0].Width;
832 mode.Height = modes[0].Height;
833 mode.Format = modes[0].Format;
834 mode.Scaling = DXGI_MODE_SCALING_CENTERED;
835 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
836 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
837 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
839 memset(&mode, 0, sizeof(mode));
840 mode.Width = modes[0].Width;
841 mode.Height = modes[0].Height;
842 mode.Format = modes[0].Format;
843 mode.Scaling = DXGI_MODE_SCALING_STRETCHED;
844 hr = IDXGIOutput_FindClosestMatchingMode(output, &mode, &matching_mode, NULL);
845 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
846 check_mode_desc(&matching_mode, &modes[0], MODE_DESC_CHECK_RESOLUTION & MODE_DESC_CHECK_FORMAT);
848 HeapFree(GetProcessHeap(), 0, modes);
850 done:
851 IDXGIOutput_Release(output);
852 IDXGIAdapter_Release(adapter);
853 refcount = IDXGIDevice_Release(device);
854 ok(!refcount, "Device has %u references left.\n", refcount);
857 struct refresh_rates
859 UINT numerator;
860 UINT denominator;
861 BOOL numerator_should_pass;
862 BOOL denominator_should_pass;
865 static void test_create_swapchain(void)
867 struct swapchain_fullscreen_state initial_state, expected_state;
868 unsigned int i, expected_width, expected_height;
869 DXGI_SWAP_CHAIN_DESC creation_desc, result_desc;
870 IDXGIDevice *device, *bgra_device;
871 ULONG refcount, expected_refcount;
872 IUnknown *obj, *obj2, *parent;
873 RECT *expected_client_rect;
874 IDXGISwapChain *swapchain;
875 IDXGISurface1 *surface;
876 IDXGIAdapter *adapter;
877 IDXGIFactory *factory;
878 IDXGIOutput *target;
879 BOOL fullscreen;
880 HRESULT hr;
882 const struct refresh_rates refresh_list[] =
884 {60, 60, FALSE, FALSE},
885 {60, 0, TRUE, FALSE},
886 {60, 1, TRUE, TRUE},
887 { 0, 60, TRUE, FALSE},
888 { 0, 0, TRUE, FALSE},
891 if (!(device = create_device(0)))
893 skip("Failed to create device, skipping tests.\n");
894 return;
897 creation_desc.OutputWindow = 0;
898 creation_desc.BufferDesc.Width = 800;
899 creation_desc.BufferDesc.Height = 600;
900 creation_desc.BufferDesc.RefreshRate.Numerator = 60;
901 creation_desc.BufferDesc.RefreshRate.Denominator = 60;
902 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
903 creation_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
904 creation_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
905 creation_desc.SampleDesc.Count = 1;
906 creation_desc.SampleDesc.Quality = 0;
907 creation_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
908 creation_desc.BufferCount = 1;
909 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
910 creation_desc.Windowed = TRUE;
911 creation_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
912 creation_desc.Flags = 0;
914 memset(&initial_state, 0, sizeof(initial_state));
915 capture_fullscreen_state(&initial_state.fullscreen_state, creation_desc.OutputWindow);
917 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
918 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
920 hr = IDXGIDevice_GetAdapter(device, &adapter);
921 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
923 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
924 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
926 expected_refcount = get_refcount((IUnknown *)adapter);
927 refcount = get_refcount((IUnknown *)factory);
928 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
929 refcount = get_refcount((IUnknown *)device);
930 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
932 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
933 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
935 refcount = get_refcount((IUnknown *)adapter);
936 ok(refcount == expected_refcount, "Got refcount %u, expected %u.\n", refcount, expected_refcount);
937 refcount = get_refcount((IUnknown *)factory);
938 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
939 refcount = get_refcount((IUnknown *)device);
940 ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
942 hr = IDXGISwapChain_GetDesc(swapchain, NULL);
943 ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr);
945 hr = IDXGISwapChain_GetParent(swapchain, &IID_IUnknown, (void **)&parent);
946 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
947 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
948 refcount = IUnknown_Release(parent);
949 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
951 hr = IDXGISwapChain_GetParent(swapchain, &IID_IDXGIFactory, (void **)&parent);
952 ok(SUCCEEDED(hr), "GetParent failed %#x.\n", hr);
953 ok(parent == (IUnknown *)factory, "Got unexpected parent interface pointer %p.\n", parent);
954 refcount = IUnknown_Release(parent);
955 todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount);
957 IDXGISwapChain_Release(swapchain);
959 refcount = get_refcount((IUnknown *)factory);
960 ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
962 for (i = 0; i < sizeof(refresh_list) / sizeof(*refresh_list); ++i)
964 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
965 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
967 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
968 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
970 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
971 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
973 ok(result_desc.Windowed == creation_desc.Windowed, "Test %u: Got unexpected windowed %#x.\n",
974 i, result_desc.Windowed);
976 todo_wine_if (!refresh_list[i].numerator_should_pass)
977 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
978 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
980 todo_wine_if (!refresh_list[i].denominator_should_pass)
981 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
982 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
984 fullscreen = 0xdeadbeef;
985 target = (void *)0xdeadbeef;
986 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
987 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
988 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
989 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
991 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
992 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
993 fullscreen = 0xdeadbeef;
994 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
995 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
996 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
997 target = (void *)0xdeadbeef;
998 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
999 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1000 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1002 check_swapchain_fullscreen_state(swapchain, &initial_state);
1003 IDXGISwapChain_Release(swapchain);
1006 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1008 /* Test GDI-compatible swapchain */
1009 bgra_device = create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT);
1010 ok(!!bgra_device, "Failed to create BGRA capable device.\n");
1012 hr = IDXGIDevice_QueryInterface(bgra_device, &IID_IUnknown, (void **)&obj2);
1013 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown.\n");
1015 hr = IDXGIFactory_CreateSwapChain(factory, obj2, &creation_desc, &swapchain);
1016 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1018 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface1, (void **)&surface);
1019 if (SUCCEEDED(hr))
1021 HDC hdc;
1023 hr = IDXGISurface1_GetDC(surface, FALSE, &hdc);
1024 ok(FAILED(hr), "Expected GetDC() to fail, %#x\n", hr);
1026 IDXGISurface1_Release(surface);
1027 IDXGISwapChain_Release(swapchain);
1029 creation_desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
1030 creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
1032 hr = IDXGIFactory_CreateSwapChain(factory, obj2, &creation_desc, &swapchain);
1033 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1035 creation_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1036 creation_desc.Flags = 0;
1038 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface1, (void **)&surface);
1039 ok(SUCCEEDED(hr), "Failed to get front buffer, hr %#x.\n", hr);
1041 hr = IDXGISurface1_GetDC(surface, FALSE, &hdc);
1042 ok(SUCCEEDED(hr), "Expected GetDC() to succeed, %#x\n", hr);
1043 IDXGISurface1_ReleaseDC(surface, NULL);
1045 IDXGISurface1_Release(surface);
1046 IDXGISwapChain_Release(swapchain);
1048 else
1050 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1051 IDXGISwapChain_Release(swapchain);
1053 IUnknown_Release(obj2);
1054 IDXGIDevice_Release(bgra_device);
1056 creation_desc.Windowed = FALSE;
1058 for (i = 0; i < sizeof(refresh_list) / sizeof(*refresh_list); ++i)
1060 creation_desc.BufferDesc.RefreshRate.Numerator = refresh_list[i].numerator;
1061 creation_desc.BufferDesc.RefreshRate.Denominator = refresh_list[i].denominator;
1063 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1064 ok(SUCCEEDED(hr), "Test %u: CreateSwapChain failed, hr %#x.\n", i, hr);
1066 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1067 ok(SUCCEEDED(hr), "Test %u: GetDesc failed, hr %#x.\n", i, hr);
1069 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1070 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1071 if (result_desc.Windowed != creation_desc.Windowed)
1072 trace("Test %u: Failed to change fullscreen state.\n", i);
1074 todo_wine_if (!refresh_list[i].numerator_should_pass)
1075 ok(result_desc.BufferDesc.RefreshRate.Numerator == refresh_list[i].numerator,
1076 "Numerator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Numerator);
1078 todo_wine_if (!refresh_list[i].denominator_should_pass)
1079 ok(result_desc.BufferDesc.RefreshRate.Denominator == refresh_list[i].denominator,
1080 "Denominator %u is %u.\n", i, result_desc.BufferDesc.RefreshRate.Denominator);
1082 fullscreen = FALSE;
1083 target = NULL;
1084 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1085 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1086 ok(fullscreen == !result_desc.Windowed, "Test %u: Got fullscreen %#x, expected %#x.\n",
1087 i, fullscreen, result_desc.Windowed);
1088 ok(result_desc.Windowed ? !target : !!target, "Test %u: Got unexpected target %p.\n", i, target);
1089 if (!result_desc.Windowed)
1091 IDXGIOutput *containing_output;
1092 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1093 ok(SUCCEEDED(hr), "Test %u: GetContainingOutput failed, hr %#x.\n", i, hr);
1094 ok(containing_output == target, "Test %u: Got unexpected containing output pointer %p.\n",
1095 i, containing_output);
1096 IDXGIOutput_Release(containing_output);
1098 ok(output_belongs_to_adapter(target, adapter),
1099 "Test %u: Output %p doesn't belong to adapter %p.\n",
1100 i, target, adapter);
1101 IDXGIOutput_Release(target);
1103 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, NULL);
1104 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1105 fullscreen = FALSE;
1106 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1107 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1108 ok(fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1109 target = NULL;
1110 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1111 ok(hr == S_OK, "Test %u: Got unexpected hr %#x.\n", i, hr);
1112 ok(!!target, "Test %u: Got unexpected target %p.\n", i, target);
1113 IDXGIOutput_Release(target);
1116 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1117 ok(SUCCEEDED(hr), "Test %u: SetFullscreenState failed, hr %#x.\n", i, hr);
1119 fullscreen = 0xdeadbeef;
1120 target = (void *)0xdeadbeef;
1121 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, &target);
1122 ok(hr == S_OK, "Test %u: GetFullscreenState failed, hr %#x.\n", i, hr);
1123 ok(!fullscreen, "Test %u: Got unexpected fullscreen %#x.\n", i, fullscreen);
1124 ok(!target, "Test %u: Got unexpected target %p.\n", i, target);
1126 check_swapchain_fullscreen_state(swapchain, &initial_state);
1127 IDXGISwapChain_Release(swapchain);
1130 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1132 /* Test swapchain creation with backbuffer width and height equal to 0. */
1133 expected_state = initial_state;
1134 expected_client_rect = &expected_state.fullscreen_state.client_rect;
1136 /* Windowed */
1137 expected_width = expected_client_rect->right;
1138 expected_height = expected_client_rect->bottom;
1140 creation_desc.BufferDesc.Width = 0;
1141 creation_desc.BufferDesc.Height = 0;
1142 creation_desc.Windowed = TRUE;
1143 creation_desc.Flags = 0;
1144 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1145 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1146 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1147 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1148 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1149 result_desc.BufferDesc.Width, expected_width);
1150 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1151 result_desc.BufferDesc.Height, expected_height);
1152 check_swapchain_fullscreen_state(swapchain, &expected_state);
1153 IDXGISwapChain_Release(swapchain);
1155 DestroyWindow(creation_desc.OutputWindow);
1156 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1157 WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
1158 0, 0, 222, 222, 0, 0, 0, 0);
1159 SetRect(&expected_state.fullscreen_state.window_rect, 0, 0, 222, 222);
1160 GetClientRect(creation_desc.OutputWindow, expected_client_rect);
1161 expected_width = expected_client_rect->right;
1162 expected_height = expected_client_rect->bottom;
1164 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1165 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1166 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1167 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1168 ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1169 result_desc.BufferDesc.Width, expected_width);
1170 ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1171 result_desc.BufferDesc.Height, expected_height);
1172 check_swapchain_fullscreen_state(swapchain, &expected_state);
1173 IDXGISwapChain_Release(swapchain);
1175 DestroyWindow(creation_desc.OutputWindow);
1176 creation_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1177 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1179 /* Fullscreen */
1180 creation_desc.Windowed = FALSE;
1181 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1182 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1183 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1184 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1185 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1186 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1187 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1188 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1189 "GetContainingOutput failed, hr %#x.\n", hr);
1190 check_swapchain_fullscreen_state(swapchain, &initial_state);
1191 IDXGISwapChain_Release(swapchain);
1192 if (hr == DXGI_ERROR_UNSUPPORTED)
1194 win_skip("GetContainingOutput() not supported.\n");
1195 goto done;
1197 if (result_desc.Windowed)
1199 win_skip("Fullscreen not supported.\n");
1200 IDXGIOutput_Release(expected_state.target);
1201 goto done;
1204 creation_desc.BufferDesc.Width = 0;
1205 creation_desc.BufferDesc.Height = 0;
1206 creation_desc.Windowed = FALSE;
1207 creation_desc.Flags = 0;
1208 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1209 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1210 expected_width = expected_client_rect->right - expected_client_rect->left;
1211 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1213 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1214 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1215 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1216 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1217 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1218 result_desc.BufferDesc.Width, expected_width);
1219 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1220 result_desc.BufferDesc.Height, expected_height);
1221 check_swapchain_fullscreen_state(swapchain, &expected_state);
1222 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1223 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1224 check_swapchain_fullscreen_state(swapchain, &initial_state);
1225 IDXGISwapChain_Release(swapchain);
1227 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
1228 creation_desc.BufferDesc.Width = 0;
1229 creation_desc.BufferDesc.Height = 0;
1230 creation_desc.Windowed = FALSE;
1231 creation_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1232 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1233 &creation_desc, &initial_state.fullscreen_state.monitor_rect, 0, 0, expected_state.target);
1234 expected_width = expected_client_rect->right - expected_client_rect->left;
1235 expected_height = expected_client_rect->bottom - expected_client_rect->top;
1237 hr = IDXGIFactory_CreateSwapChain(factory, obj, &creation_desc, &swapchain);
1238 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1239 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
1240 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1241 todo_wine ok(result_desc.BufferDesc.Width == expected_width, "Got width %u, expected %u.\n",
1242 result_desc.BufferDesc.Width, expected_width);
1243 todo_wine ok(result_desc.BufferDesc.Height == expected_height, "Got height %u, expected %u.\n",
1244 result_desc.BufferDesc.Height, expected_height);
1245 check_swapchain_fullscreen_state(swapchain, &expected_state);
1246 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1247 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1248 check_swapchain_fullscreen_state(swapchain, &initial_state);
1249 IDXGISwapChain_Release(swapchain);
1251 IDXGIOutput_Release(expected_state.target);
1253 done:
1254 IUnknown_Release(obj);
1255 refcount = IDXGIDevice_Release(device);
1256 ok(!refcount, "Device has %u references left.\n", refcount);
1257 refcount = IDXGIAdapter_Release(adapter);
1258 ok(!refcount, "Adapter has %u references left.\n", refcount);
1259 refcount = IDXGIFactory_Release(factory);
1260 ok(!refcount, "Factory has %u references left.\n", refcount);
1261 check_window_fullscreen_state(creation_desc.OutputWindow, &initial_state.fullscreen_state);
1262 DestroyWindow(creation_desc.OutputWindow);
1265 static void test_get_containing_output(void)
1267 unsigned int output_count, output_idx;
1268 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1269 IDXGIOutput *output, *output2;
1270 DXGI_OUTPUT_DESC output_desc;
1271 MONITORINFOEXW monitor_info;
1272 IDXGISwapChain *swapchain;
1273 IDXGIFactory *factory;
1274 IDXGIAdapter *adapter;
1275 POINT points[4 * 16];
1276 IDXGIDevice *device;
1277 unsigned int i, j;
1278 HMONITOR monitor;
1279 ULONG refcount;
1280 HRESULT hr;
1281 BOOL ret;
1283 if (!(device = create_device(0)))
1285 skip("Failed to create device.\n");
1286 return;
1289 hr = IDXGIDevice_GetAdapter(device, &adapter);
1290 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1292 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1293 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1295 swapchain_desc.BufferDesc.Width = 100;
1296 swapchain_desc.BufferDesc.Height = 100;
1297 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1298 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1299 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1300 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1301 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1302 swapchain_desc.SampleDesc.Count = 1;
1303 swapchain_desc.SampleDesc.Quality = 0;
1304 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1305 swapchain_desc.BufferCount = 1;
1306 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1307 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1308 swapchain_desc.Windowed = TRUE;
1309 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1310 swapchain_desc.Flags = 0;
1312 output_count = 0;
1313 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1315 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_count, hr);
1316 IDXGIOutput_Release(output);
1317 ++output_count;
1320 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1321 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1323 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, 0);
1324 ok(!!monitor, "MonitorFromWindow failed.\n");
1326 monitor_info.cbSize = sizeof(monitor_info);
1327 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1328 ok(ret, "Failed to get monitor info.\n");
1330 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1331 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1332 "GetContainingOutput failed, hr %#x.\n", hr);
1333 if (hr == DXGI_ERROR_UNSUPPORTED)
1335 win_skip("GetContainingOutput() not supported.\n");
1336 IDXGISwapChain_Release(swapchain);
1337 goto done;
1340 hr = IDXGIOutput_GetDesc(output, &output_desc);
1341 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1343 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1344 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1345 ok(output != output2, "Got unexpected output pointers %p, %p.\n", output, output2);
1346 check_output_equal(output, output2);
1348 refcount = IDXGIOutput_Release(output);
1349 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1350 refcount = IDXGIOutput_Release(output2);
1351 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1353 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1354 "Got unexpected device name %s, expected %s.\n",
1355 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1356 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1357 "Got unexpected desktop coordinates %s, expected %s.\n",
1358 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1359 wine_dbgstr_rect(&monitor_info.rcMonitor));
1361 output_idx = 0;
1362 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1364 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1366 hr = IDXGIOutput_GetDesc(output, &output_desc);
1367 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1369 /* Move the OutputWindow to the current output. */
1370 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
1371 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
1372 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1373 ok(ret, "SetWindowPos failed.\n");
1375 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output2);
1376 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1378 check_output_equal(output, output2);
1380 refcount = IDXGIOutput_Release(output2);
1381 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1382 refcount = IDXGIOutput_Release(output);
1383 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1384 ++output_idx;
1386 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
1387 for (i = 0; i < 4; ++i)
1389 static const POINT offsets[] =
1391 { 0, 0},
1392 {-49, 0}, {-50, 0}, {-51, 0},
1393 { 0, -49}, { 0, -50}, { 0, -51},
1394 {-49, -49}, {-50, -49}, {-51, -49},
1395 {-49, -50}, {-50, -50}, {-51, -50},
1396 {-49, -51}, {-50, -51}, {-51, -51},
1398 unsigned int x, y;
1400 switch (i)
1402 case 0:
1403 x = output_desc.DesktopCoordinates.left;
1404 y = output_desc.DesktopCoordinates.top;
1405 break;
1406 case 1:
1407 x = output_desc.DesktopCoordinates.right;
1408 y = output_desc.DesktopCoordinates.top;
1409 break;
1410 case 2:
1411 x = output_desc.DesktopCoordinates.right;
1412 y = output_desc.DesktopCoordinates.bottom;
1413 break;
1414 case 3:
1415 x = output_desc.DesktopCoordinates.left;
1416 y = output_desc.DesktopCoordinates.bottom;
1417 break;
1420 for (j = 0; j < sizeof(offsets) / sizeof(*offsets); ++j)
1422 unsigned int idx = (sizeof(offsets) / sizeof(*offsets)) * i + j;
1423 assert(idx < sizeof(points) / sizeof(*points));
1424 points[idx].x = x + offsets[j].x;
1425 points[idx].y = y + offsets[j].y;
1429 for (i = 0; i < sizeof(points) / sizeof(*points); ++i)
1431 ret = SetWindowPos(swapchain_desc.OutputWindow, 0, points[i].x, points[i].y,
1432 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1433 ok(ret, "SetWindowPos failed.\n");
1435 monitor = MonitorFromWindow(swapchain_desc.OutputWindow, MONITOR_DEFAULTTONEAREST);
1436 ok(!!monitor, "MonitorFromWindow failed.\n");
1438 monitor_info.cbSize = sizeof(monitor_info);
1439 ret = GetMonitorInfoW(monitor, (MONITORINFO *)&monitor_info);
1440 ok(ret, "Failed to get monitor info.\n");
1442 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
1443 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1444 ok(!!output, "Got unexpected containing output %p.\n", output);
1445 hr = IDXGIOutput_GetDesc(output, &output_desc);
1446 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1447 refcount = IDXGIOutput_Release(output);
1448 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1450 ok(!lstrcmpW(output_desc.DeviceName, monitor_info.szDevice),
1451 "Got unexpected device name %s, expected %s.\n",
1452 wine_dbgstr_w(output_desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
1453 ok(EqualRect(&output_desc.DesktopCoordinates, &monitor_info.rcMonitor),
1454 "Got unexpected desktop coordinates %s, expected %s.\n",
1455 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1456 wine_dbgstr_rect(&monitor_info.rcMonitor));
1460 refcount = IDXGISwapChain_Release(swapchain);
1461 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1463 done:
1464 refcount = IDXGIDevice_Release(device);
1465 ok(!refcount, "Device has %u references left.\n", refcount);
1466 refcount = IDXGIAdapter_Release(adapter);
1467 ok(!refcount, "Adapter has %u references left.\n", refcount);
1468 refcount = IDXGIFactory_Release(factory);
1469 ok(!refcount, "Factory has %u references left.\n", refcount);
1470 DestroyWindow(swapchain_desc.OutputWindow);
1473 static void test_swapchain_fullscreen_state(IDXGISwapChain *swapchain,
1474 IDXGIAdapter *adapter, const struct swapchain_fullscreen_state *initial_state)
1476 MONITORINFOEXW monitor_info, *output_monitor_info;
1477 struct swapchain_fullscreen_state expected_state;
1478 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1479 DXGI_OUTPUT_DESC output_desc;
1480 unsigned int i, output_count;
1481 IDXGIOutput *output;
1482 HRESULT hr;
1483 BOOL ret;
1485 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1486 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1488 check_swapchain_fullscreen_state(swapchain, initial_state);
1490 expected_state = *initial_state;
1491 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1492 &swapchain_desc, &initial_state->fullscreen_state.monitor_rect, 800, 600, NULL);
1493 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
1494 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1496 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1497 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1498 check_swapchain_fullscreen_state(swapchain, &expected_state);
1500 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1501 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1502 check_swapchain_fullscreen_state(swapchain, &expected_state);
1504 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1505 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1506 check_swapchain_fullscreen_state(swapchain, initial_state);
1508 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1509 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1510 check_swapchain_fullscreen_state(swapchain, initial_state);
1512 IDXGIOutput_Release(expected_state.target);
1513 expected_state.target = NULL;
1515 output_count = 0;
1516 while (IDXGIAdapter_EnumOutputs(adapter, output_count, &output) != DXGI_ERROR_NOT_FOUND)
1518 IDXGIOutput_Release(output);
1519 ++output_count;
1522 output_monitor_info = HeapAlloc(GetProcessHeap(), 0, output_count * sizeof(*output_monitor_info));
1523 ok(!!output_monitor_info, "Failed to allocate memory.\n");
1524 for (i = 0; i < output_count; ++i)
1526 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1527 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1529 hr = IDXGIOutput_GetDesc(output, &output_desc);
1530 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1532 output_monitor_info[i].cbSize = sizeof(*output_monitor_info);
1533 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&output_monitor_info[i]);
1534 ok(ret, "Failed to get monitor info.\n");
1536 IDXGIOutput_Release(output);
1539 for (i = 0; i < output_count; ++i)
1541 RECT orig_monitor_rect = output_monitor_info[i].rcMonitor;
1542 IDXGIOutput *target;
1543 BOOL fullscreen;
1545 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1546 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1547 hr = IDXGIOutput_GetDesc(output, &output_desc);
1548 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1550 expected_state = *initial_state;
1551 expected_state.target = output;
1552 expected_state.fullscreen_state.monitor = output_desc.Monitor;
1553 expected_state.fullscreen_state.monitor_rect = orig_monitor_rect;
1554 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1555 &swapchain_desc, &orig_monitor_rect, 800, 600, NULL);
1557 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1558 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1559 check_swapchain_fullscreen_state(swapchain, &expected_state);
1561 target = NULL;
1562 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1563 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1564 ok(target == output, "Got target pointer %p, expected %p.\n", target, output);
1565 IDXGIOutput_Release(target);
1566 fullscreen = FALSE;
1567 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1568 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1569 ok(fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1571 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1572 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1573 check_swapchain_fullscreen_state(swapchain, &expected_state);
1574 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, output);
1575 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
1576 check_swapchain_fullscreen_state(swapchain, &expected_state);
1577 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1578 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1579 check_swapchain_fullscreen_state(swapchain, initial_state);
1581 fullscreen = TRUE;
1582 hr = IDXGISwapChain_GetFullscreenState(swapchain, &fullscreen, NULL);
1583 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1584 ok(!fullscreen, "Got unexpected fullscreen %#x.\n", hr);
1586 check_swapchain_fullscreen_state(swapchain, initial_state);
1587 monitor_info.cbSize = sizeof(monitor_info);
1588 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1589 ok(ret, "Failed to get monitor info.\n");
1590 ok(EqualRect(&monitor_info.rcMonitor, &orig_monitor_rect), "Got monitor rect %s, expected %s.\n",
1591 wine_dbgstr_rect(&monitor_info.rcMonitor), wine_dbgstr_rect(&orig_monitor_rect));
1593 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
1594 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1596 IDXGIOutput_Release(output);
1599 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1600 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1601 check_swapchain_fullscreen_state(swapchain, initial_state);
1603 for (i = 0; i < output_count; ++i)
1605 hr = IDXGIAdapter_EnumOutputs(adapter, i, &output);
1606 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1608 hr = IDXGIOutput_GetDesc(output, &output_desc);
1609 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1611 monitor_info.cbSize = sizeof(monitor_info);
1612 ret = GetMonitorInfoW(output_desc.Monitor, (MONITORINFO *)&monitor_info);
1613 ok(ret, "Failed to get monitor info.\n");
1615 ok(EqualRect(&monitor_info.rcMonitor, &output_monitor_info[i].rcMonitor),
1616 "Got monitor rect %s, expected %s.\n",
1617 wine_dbgstr_rect(&monitor_info.rcMonitor),
1618 wine_dbgstr_rect(&output_monitor_info[i].rcMonitor));
1620 IDXGIOutput_Release(output);
1623 HeapFree(GetProcessHeap(), 0, output_monitor_info);
1626 static void test_set_fullscreen(void)
1628 struct swapchain_fullscreen_state initial_state;
1629 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1630 IDXGISwapChain *swapchain;
1631 IDXGIFactory *factory;
1632 IDXGIAdapter *adapter;
1633 IDXGIDevice *device;
1634 ULONG refcount;
1635 HRESULT hr;
1637 if (!(device = create_device(0)))
1639 skip("Failed to create device.\n");
1640 return;
1643 hr = IDXGIDevice_GetAdapter(device, &adapter);
1644 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1646 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1647 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1649 swapchain_desc.BufferDesc.Width = 800;
1650 swapchain_desc.BufferDesc.Height = 600;
1651 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1652 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1653 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1654 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1655 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1656 swapchain_desc.SampleDesc.Count = 1;
1657 swapchain_desc.SampleDesc.Quality = 0;
1658 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1659 swapchain_desc.BufferCount = 1;
1660 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1661 swapchain_desc.Windowed = TRUE;
1662 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1663 swapchain_desc.Flags = 0;
1665 memset(&initial_state, 0, sizeof(initial_state));
1666 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
1667 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1668 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1669 check_swapchain_fullscreen_state(swapchain, &initial_state);
1670 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1671 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE ||
1672 broken(hr == DXGI_ERROR_UNSUPPORTED), /* Win 7 testbot */
1673 "SetFullscreenState failed, hr %#x.\n", hr);
1674 if (FAILED(hr))
1676 skip("Could not change fullscreen state.\n");
1677 goto done;
1679 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1680 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1681 refcount = IDXGISwapChain_Release(swapchain);
1682 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1684 DestroyWindow(swapchain_desc.OutputWindow);
1685 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1686 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1687 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1688 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1689 check_swapchain_fullscreen_state(swapchain, &initial_state);
1690 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1691 refcount = IDXGISwapChain_Release(swapchain);
1692 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1694 DestroyWindow(swapchain_desc.OutputWindow);
1695 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
1696 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1697 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
1698 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1699 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1700 check_swapchain_fullscreen_state(swapchain, &initial_state);
1701 test_swapchain_fullscreen_state(swapchain, adapter, &initial_state);
1703 done:
1704 refcount = IDXGISwapChain_Release(swapchain);
1705 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1706 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
1707 DestroyWindow(swapchain_desc.OutputWindow);
1709 IDXGIAdapter_Release(adapter);
1710 refcount = IDXGIDevice_Release(device);
1711 ok(!refcount, "Device has %u references left.\n", refcount);
1712 refcount = IDXGIFactory_Release(factory);
1713 ok(!refcount, "Factory has %u references left.\n", refcount);
1716 static void test_default_fullscreen_target_output(void)
1718 IDXGIOutput *output, *containing_output, *target;
1719 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1720 DXGI_OUTPUT_DESC output_desc;
1721 IDXGISwapChain *swapchain;
1722 unsigned int output_idx;
1723 IDXGIFactory *factory;
1724 IDXGIAdapter *adapter;
1725 IDXGIDevice *device;
1726 ULONG refcount;
1727 HRESULT hr;
1728 BOOL ret;
1730 if (!(device = create_device(0)))
1732 skip("Failed to create device.\n");
1733 return;
1736 hr = IDXGIDevice_GetAdapter(device, &adapter);
1737 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
1739 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
1740 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
1742 swapchain_desc.BufferDesc.Width = 100;
1743 swapchain_desc.BufferDesc.Height = 100;
1744 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
1745 swapchain_desc.BufferDesc.RefreshRate.Denominator = 60;
1746 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
1747 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
1748 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
1749 swapchain_desc.SampleDesc.Count = 1;
1750 swapchain_desc.SampleDesc.Quality = 0;
1751 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
1752 swapchain_desc.BufferCount = 1;
1753 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test",
1754 WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 100, 100, 0, 0, 0, 0);
1755 swapchain_desc.Windowed = TRUE;
1756 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
1757 swapchain_desc.Flags = 0;
1759 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
1760 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
1762 output_idx = 0;
1763 while ((hr = IDXGIAdapter_EnumOutputs(adapter, output_idx, &output)) != DXGI_ERROR_NOT_FOUND)
1765 ok(SUCCEEDED(hr), "Failed to enumerate output %u, hr %#x.\n", output_idx, hr);
1767 hr = IDXGIOutput_GetDesc(output, &output_desc);
1768 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1770 /* Move the OutputWindow to the current output. */
1771 ret = SetWindowPos(swapchain_desc.OutputWindow, 0,
1772 output_desc.DesktopCoordinates.left, output_desc.DesktopCoordinates.top,
1773 0, 0, SWP_NOSIZE | SWP_NOZORDER);
1774 ok(ret, "SetWindowPos failed.\n");
1776 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1777 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
1778 "GetContainingOutput failed, hr %#x.\n", hr);
1779 if (hr == DXGI_ERROR_UNSUPPORTED)
1781 win_skip("GetContainingOutput() not supported.\n");
1782 IDXGIOutput_Release(output);
1783 goto done;
1786 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
1787 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
1788 "SetFullscreenState failed, hr %#x.\n", hr);
1789 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
1791 skip("Could not change fullscreen state.\n");
1792 IDXGIOutput_Release(containing_output);
1793 IDXGIOutput_Release(output);
1794 goto done;
1797 target = NULL;
1798 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1799 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1800 ok(target != containing_output, "Got unexpected output pointers %p, %p.\n",
1801 target, containing_output);
1802 check_output_equal(target, containing_output);
1804 refcount = IDXGIOutput_Release(containing_output);
1805 ok(!refcount, "IDXGIOutput has %u references left.\n", refcount);
1807 hr = IDXGISwapChain_GetContainingOutput(swapchain, &containing_output);
1808 ok(SUCCEEDED(hr), "GetContainingOutput failed, hr %#x.\n", hr);
1809 ok(containing_output == target, "Got unexpected containing output %p, expected %p.\n",
1810 containing_output, target);
1811 refcount = IDXGIOutput_Release(containing_output);
1812 ok(refcount >= 2, "Got unexpected refcount %u.\n", refcount);
1813 refcount = IDXGIOutput_Release(target);
1814 ok(refcount >= 1, "Got unexpected refcount %u.\n", refcount);
1816 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
1817 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
1819 IDXGIOutput_Release(output);
1820 ++output_idx;
1823 done:
1824 refcount = IDXGISwapChain_Release(swapchain);
1825 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
1827 refcount = IDXGIDevice_Release(device);
1828 ok(!refcount, "Device has %u references left.\n", refcount);
1829 refcount = IDXGIAdapter_Release(adapter);
1830 ok(!refcount, "Adapter has %u references left.\n", refcount);
1831 refcount = IDXGIFactory_Release(factory);
1832 ok(!refcount, "Factory has %u references left.\n", refcount);
1833 DestroyWindow(swapchain_desc.OutputWindow);
1836 static void test_windowed_resize_target(IDXGISwapChain *swapchain, HWND window,
1837 struct swapchain_fullscreen_state *state)
1839 struct swapchain_fullscreen_state expected_state;
1840 struct fullscreen_state *e;
1841 DXGI_MODE_DESC mode;
1842 RECT window_rect;
1843 unsigned int i;
1844 HRESULT hr;
1845 BOOL ret;
1847 static const struct
1849 unsigned int width, height;
1851 sizes[] =
1853 {200, 200},
1854 {400, 200},
1855 {400, 400},
1856 {600, 800},
1857 {1000, 600},
1858 {1600, 100},
1859 {2000, 1000},
1862 check_swapchain_fullscreen_state(swapchain, state);
1863 expected_state = *state;
1864 e = &expected_state.fullscreen_state;
1866 for (i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i)
1868 SetRect(&e->client_rect, 0, 0, sizes[i].width, sizes[i].height);
1869 e->window_rect = e->client_rect;
1870 ret = AdjustWindowRectEx(&e->window_rect, GetWindowLongW(window, GWL_STYLE),
1871 FALSE, GetWindowLongW(window, GWL_EXSTYLE));
1872 ok(ret, "AdjustWindowRectEx failed.\n");
1873 if (GetMenu(window))
1874 e->client_rect.bottom -= GetSystemMetrics(SM_CYMENU);
1875 SetRect(&e->window_rect, 0, 0,
1876 e->window_rect.right - e->window_rect.left,
1877 e->window_rect.bottom - e->window_rect.top);
1878 GetWindowRect(window, &window_rect);
1879 OffsetRect(&e->window_rect, window_rect.left, window_rect.top);
1880 if (e->window_rect.right >= e->monitor_rect.right
1881 || e->window_rect.bottom >= e->monitor_rect.bottom)
1883 skip("Test %u: Window %s does not fit on screen %s.\n",
1884 i, wine_dbgstr_rect(&e->window_rect), wine_dbgstr_rect(&e->monitor_rect));
1885 continue;
1888 memset(&mode, 0, sizeof(mode));
1889 mode.Width = sizes[i].width;
1890 mode.Height = sizes[i].height;
1891 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
1892 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1893 check_swapchain_fullscreen_state(swapchain, &expected_state);
1896 ret = MoveWindow(window, 0, 0, 0, 0, TRUE);
1897 ok(ret, "MoveWindow failed.\n");
1898 GetWindowRect(window, &e->window_rect);
1899 GetClientRect(window, &e->client_rect);
1900 ret = MoveWindow(window, 0, 0, 200, 200, TRUE);
1902 memset(&mode, 0, sizeof(mode));
1903 hr = IDXGISwapChain_ResizeTarget(swapchain, &mode);
1904 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1905 check_swapchain_fullscreen_state(swapchain, &expected_state);
1907 GetWindowRect(window, &e->window_rect);
1908 GetClientRect(window, &e->client_rect);
1909 *state = expected_state;
1912 static void test_fullscreen_resize_target(IDXGISwapChain *swapchain,
1913 const struct swapchain_fullscreen_state *initial_state)
1915 struct swapchain_fullscreen_state expected_state;
1916 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1917 DXGI_OUTPUT_DESC output_desc;
1918 unsigned int i, mode_count;
1919 DXGI_MODE_DESC *modes;
1920 IDXGIOutput *target;
1921 HRESULT hr;
1923 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
1924 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1926 hr = IDXGISwapChain_GetFullscreenState(swapchain, NULL, &target);
1927 ok(SUCCEEDED(hr), "GetFullscreenState failed, hr %#x.\n", hr);
1929 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, NULL);
1930 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE), /* Win 7 testbot */
1931 "Failed to list modes, hr %#x.\n", hr);
1932 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
1934 win_skip("GetDisplayModeList() not supported.\n");
1935 IDXGIOutput_Release(target);
1936 return;
1939 modes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*modes) * mode_count);
1940 ok(!!modes, "Failed to allocate memory.\n");
1942 hr = IDXGIOutput_GetDisplayModeList(target, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &mode_count, modes);
1943 ok(SUCCEEDED(hr), "Failed to list modes, hr %#x.\n", hr);
1945 expected_state = *initial_state;
1946 for (i = 0; i < min(mode_count, 20); ++i)
1948 /* FIXME: Modes with scaling aren't fully tested. */
1949 if (!(swapchain_desc.Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
1950 && modes[i].Scaling != DXGI_MODE_SCALING_UNSPECIFIED)
1951 continue;
1953 hr = IDXGIOutput_GetDesc(target, &output_desc);
1954 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1956 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
1957 &swapchain_desc, &output_desc.DesktopCoordinates, modes[i].Width, modes[i].Height, NULL);
1959 hr = IDXGISwapChain_ResizeTarget(swapchain, &modes[i]);
1960 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
1961 check_swapchain_fullscreen_state(swapchain, &expected_state);
1963 hr = IDXGIOutput_GetDesc(target, &output_desc);
1964 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
1965 ok(EqualRect(&output_desc.DesktopCoordinates, &expected_state.fullscreen_state.monitor_rect),
1966 "Got desktop coordinates %s, expected %s.\n",
1967 wine_dbgstr_rect(&output_desc.DesktopCoordinates),
1968 wine_dbgstr_rect(&expected_state.fullscreen_state.monitor_rect));
1971 HeapFree(GetProcessHeap(), 0, modes);
1972 IDXGIOutput_Release(target);
1975 static void test_resize_target(void)
1977 struct swapchain_fullscreen_state initial_state, expected_state;
1978 DXGI_SWAP_CHAIN_DESC swapchain_desc;
1979 IDXGISwapChain *swapchain;
1980 IDXGIFactory *factory;
1981 IDXGIAdapter *adapter;
1982 IDXGIDevice *device;
1983 unsigned int i;
1984 ULONG refcount;
1985 HRESULT hr;
1987 static const struct
1989 POINT origin;
1990 BOOL fullscreen;
1991 BOOL menu;
1992 unsigned int flags;
1994 tests[] =
1996 {{ 0, 0}, TRUE, FALSE, 0},
1997 {{10, 10}, TRUE, FALSE, 0},
1998 {{ 0, 0}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
1999 {{10, 10}, TRUE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2000 {{ 0, 0}, FALSE, FALSE, 0},
2001 {{ 0, 0}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2002 {{10, 10}, FALSE, FALSE, 0},
2003 {{10, 10}, FALSE, FALSE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2004 {{ 0, 0}, FALSE, TRUE, 0},
2005 {{ 0, 0}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2006 {{10, 10}, FALSE, TRUE, 0},
2007 {{10, 10}, FALSE, TRUE, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH},
2010 if (!(device = create_device(0)))
2012 skip("Failed to create device.\n");
2013 return;
2016 hr = IDXGIDevice_GetAdapter(device, &adapter);
2017 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2019 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2020 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2022 swapchain_desc.BufferDesc.Width = 800;
2023 swapchain_desc.BufferDesc.Height = 600;
2024 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2025 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2026 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2027 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2028 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2029 swapchain_desc.SampleDesc.Count = 1;
2030 swapchain_desc.SampleDesc.Quality = 0;
2031 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2032 swapchain_desc.BufferCount = 1;
2033 swapchain_desc.Windowed = TRUE;
2034 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2035 swapchain_desc.Flags = 0;
2037 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
2039 swapchain_desc.Flags = tests[i].flags;
2040 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0,
2041 tests[i].origin.x, tests[i].origin.y, 400, 200, 0, 0, 0, 0);
2042 if (tests[i].menu)
2044 HMENU menu_bar = CreateMenu();
2045 HMENU menu = CreateMenu();
2046 AppendMenuA(menu_bar, MF_POPUP, (UINT_PTR)menu, "Menu");
2047 SetMenu(swapchain_desc.OutputWindow, menu_bar);
2050 memset(&initial_state, 0, sizeof(initial_state));
2051 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
2053 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2054 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2055 check_swapchain_fullscreen_state(swapchain, &initial_state);
2057 expected_state = initial_state;
2058 if (tests[i].fullscreen)
2060 expected_state.fullscreen = TRUE;
2061 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2062 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect, 800, 600, NULL);
2063 hr = IDXGISwapChain_GetContainingOutput(swapchain, &expected_state.target);
2064 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2065 "GetContainingOutput failed, hr %#x.\n", hr);
2066 if (hr == DXGI_ERROR_UNSUPPORTED)
2068 win_skip("GetContainingOutput() not supported.\n");
2069 IDXGISwapChain_Release(swapchain);
2070 DestroyWindow(swapchain_desc.OutputWindow);
2071 continue;
2074 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, NULL);
2075 ok(SUCCEEDED(hr) || hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE,
2076 "SetFullscreenState failed, hr %#x.\n", hr);
2077 if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE)
2079 skip("Could not change fullscreen state.\n");
2080 IDXGIOutput_Release(expected_state.target);
2081 IDXGISwapChain_Release(swapchain);
2082 DestroyWindow(swapchain_desc.OutputWindow);
2083 continue;
2086 check_swapchain_fullscreen_state(swapchain, &expected_state);
2088 hr = IDXGISwapChain_ResizeTarget(swapchain, NULL);
2089 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2090 check_swapchain_fullscreen_state(swapchain, &expected_state);
2092 if (tests[i].fullscreen)
2094 test_fullscreen_resize_target(swapchain, &expected_state);
2096 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2097 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2098 check_swapchain_fullscreen_state(swapchain, &initial_state);
2099 IDXGIOutput_Release(expected_state.target);
2100 check_swapchain_fullscreen_state(swapchain, &initial_state);
2101 expected_state = initial_state;
2103 else
2105 test_windowed_resize_target(swapchain, swapchain_desc.OutputWindow, &expected_state);
2107 check_swapchain_fullscreen_state(swapchain, &expected_state);
2110 refcount = IDXGISwapChain_Release(swapchain);
2111 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2112 check_window_fullscreen_state(swapchain_desc.OutputWindow, &expected_state.fullscreen_state);
2113 DestroyWindow(swapchain_desc.OutputWindow);
2116 IDXGIAdapter_Release(adapter);
2117 refcount = IDXGIDevice_Release(device);
2118 ok(!refcount, "Device has %u references left.\n", refcount);
2119 refcount = IDXGIFactory_Release(factory);
2120 ok(!refcount, "Factory has %u references left.\n", refcount);
2123 static void test_inexact_modes(void)
2125 struct swapchain_fullscreen_state initial_state, expected_state;
2126 DXGI_SWAP_CHAIN_DESC swapchain_desc, result_desc;
2127 IDXGIOutput *output = NULL;
2128 IDXGISwapChain *swapchain;
2129 IDXGIFactory *factory;
2130 IDXGIAdapter *adapter;
2131 IDXGIDevice *device;
2132 unsigned int i;
2133 ULONG refcount;
2134 HRESULT hr;
2136 static const struct
2138 unsigned int width, height;
2140 sizes[] =
2142 {101, 101},
2143 {203, 204},
2144 {799, 601},
2147 if (!(device = create_device(0)))
2149 skip("Failed to create device.\n");
2150 return;
2153 hr = IDXGIDevice_GetAdapter(device, &adapter);
2154 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2156 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2157 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2159 swapchain_desc.BufferDesc.Width = 800;
2160 swapchain_desc.BufferDesc.Height = 600;
2161 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2162 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2163 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2164 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2165 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2166 swapchain_desc.SampleDesc.Count = 1;
2167 swapchain_desc.SampleDesc.Quality = 0;
2168 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2169 swapchain_desc.BufferCount = 1;
2170 swapchain_desc.OutputWindow = CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2171 swapchain_desc.Windowed = FALSE;
2172 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2173 swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
2175 memset(&initial_state, 0, sizeof(initial_state));
2176 capture_fullscreen_state(&initial_state.fullscreen_state, swapchain_desc.OutputWindow);
2178 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2179 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2180 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2181 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2182 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2183 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2184 hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
2185 ok(SUCCEEDED(hr) || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win 7 testbot */,
2186 "GetContainingOutput failed, hr %#x.\n", hr);
2187 refcount = IDXGISwapChain_Release(swapchain);
2188 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2189 if (hr == DXGI_ERROR_UNSUPPORTED)
2191 win_skip("GetContainingOutput() not supported.\n");
2192 goto done;
2194 if (result_desc.Windowed)
2196 win_skip("Fullscreen not supported.\n");
2197 goto done;
2200 check_window_fullscreen_state(swapchain_desc.OutputWindow, &initial_state.fullscreen_state);
2202 for (i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i)
2204 /* Test CreateSwapChain(). */
2205 swapchain_desc.BufferDesc.Width = sizes[i].width;
2206 swapchain_desc.BufferDesc.Height = sizes[i].height;
2207 swapchain_desc.Windowed = FALSE;
2209 expected_state = initial_state;
2210 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state,
2211 &swapchain_desc, &initial_state.fullscreen_state.monitor_rect,
2212 sizes[i].width, sizes[i].height, output);
2214 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2215 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2217 check_swapchain_fullscreen_state(swapchain, &expected_state);
2218 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2219 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2220 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2221 result_desc.BufferDesc.Width, sizes[i].width);
2222 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2223 result_desc.BufferDesc.Height, sizes[i].height);
2225 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2226 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2227 check_swapchain_fullscreen_state(swapchain, &initial_state);
2229 refcount = IDXGISwapChain_Release(swapchain);
2230 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2232 /* Test SetFullscreenState(). */
2233 swapchain_desc.BufferDesc.Width = sizes[i].width;
2234 swapchain_desc.BufferDesc.Height = sizes[i].height;
2235 swapchain_desc.Windowed = TRUE;
2237 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2238 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2240 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2241 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2243 check_swapchain_fullscreen_state(swapchain, &expected_state);
2244 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2245 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2246 ok(result_desc.BufferDesc.Width == sizes[i].width, "Got width %u, expected %u.\n",
2247 result_desc.BufferDesc.Width, sizes[i].width);
2248 ok(result_desc.BufferDesc.Height == sizes[i].height, "Got height %u, expected %u.\n",
2249 result_desc.BufferDesc.Height, sizes[i].height);
2251 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2252 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2253 check_swapchain_fullscreen_state(swapchain, &initial_state);
2255 refcount = IDXGISwapChain_Release(swapchain);
2256 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2258 /* Test ResizeTarget(). */
2259 swapchain_desc.BufferDesc.Width = 800;
2260 swapchain_desc.BufferDesc.Height = 600;
2261 swapchain_desc.Windowed = TRUE;
2263 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2264 ok(SUCCEEDED(hr), "CreateSwapChain failed, hr %#x.\n", hr);
2266 hr = IDXGISwapChain_SetFullscreenState(swapchain, TRUE, output);
2267 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2269 swapchain_desc.BufferDesc.Width = sizes[i].width;
2270 swapchain_desc.BufferDesc.Height = sizes[i].height;
2271 hr = IDXGISwapChain_ResizeTarget(swapchain, &swapchain_desc.BufferDesc);
2272 ok(SUCCEEDED(hr), "ResizeTarget failed, hr %#x.\n", hr);
2274 check_swapchain_fullscreen_state(swapchain, &expected_state);
2275 hr = IDXGISwapChain_GetDesc(swapchain, &result_desc);
2276 ok(SUCCEEDED(hr), "GetDesc failed, hr %#x.\n", hr);
2277 ok(result_desc.BufferDesc.Width == 800, "Got width %u.\n", result_desc.BufferDesc.Width);
2278 ok(result_desc.BufferDesc.Height == 600, "Got height %u.\n", result_desc.BufferDesc.Height);
2280 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2281 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2282 check_swapchain_fullscreen_state(swapchain, &initial_state);
2284 refcount = IDXGISwapChain_Release(swapchain);
2285 ok(!refcount, "IDXGISwapChain has %u references left.\n", refcount);
2288 done:
2289 if (output)
2290 IDXGIOutput_Release(output);
2291 IDXGIAdapter_Release(adapter);
2292 refcount = IDXGIDevice_Release(device);
2293 ok(!refcount, "Device has %u references left.\n", refcount);
2294 refcount = IDXGIFactory_Release(factory);
2295 ok(!refcount, "Factory has %u references left.\n", refcount);
2298 static void test_create_factory(void)
2300 IDXGIFactory1 *factory;
2301 IUnknown *iface;
2302 HRESULT hr;
2304 iface = (void *)0xdeadbeef;
2305 hr = CreateDXGIFactory(&IID_IDXGIDevice, (void **)&iface);
2306 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2307 ok(!iface, "Got unexpected iface %p.\n", iface);
2309 hr = CreateDXGIFactory(&IID_IUnknown, (void **)&iface);
2310 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2311 IUnknown_Release(iface);
2313 hr = CreateDXGIFactory(&IID_IDXGIObject, (void **)&iface);
2314 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2315 IUnknown_Release(iface);
2317 factory = (void *)0xdeadbeef;
2318 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&iface);
2319 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2320 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
2321 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2322 ok(!factory, "Got unexpected factory %p.\n", factory);
2323 IUnknown_Release(iface);
2325 iface = (void *)0xdeadbeef;
2326 hr = CreateDXGIFactory(&IID_IDXGIFactory1, (void **)&iface);
2327 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2328 ok(!iface, "Got unexpected iface %p.\n", iface);
2330 if (!pCreateDXGIFactory1)
2332 win_skip("CreateDXGIFactory1 not available, skipping tests.\n");
2333 return;
2336 iface = (void *)0xdeadbeef;
2337 hr = pCreateDXGIFactory1(&IID_IDXGIDevice, (void **)&iface);
2338 ok(hr == E_NOINTERFACE, "Got unexpected hr %#x.\n", hr);
2339 ok(!iface, "Got unexpected iface %p.\n", iface);
2341 hr = pCreateDXGIFactory1(&IID_IUnknown, (void **)&iface);
2342 ok(SUCCEEDED(hr), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr);
2343 IUnknown_Release(iface);
2345 hr = pCreateDXGIFactory1(&IID_IDXGIObject, (void **)&iface);
2346 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr);
2347 IUnknown_Release(iface);
2349 hr = pCreateDXGIFactory1(&IID_IDXGIFactory, (void **)&iface);
2350 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr);
2351 hr = IUnknown_QueryInterface(iface, &IID_IDXGIFactory1, (void **)&factory);
2352 ok(SUCCEEDED(hr), "Failed to query IDXGIFactory1 interface, hr %#x.\n", hr);
2353 IDXGIFactory1_Release(factory);
2354 IUnknown_Release(iface);
2356 hr = pCreateDXGIFactory1(&IID_IDXGIFactory1, (void **)&iface);
2357 ok(SUCCEEDED(hr), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr);
2358 IUnknown_Release(iface);
2361 static void test_private_data(void)
2363 ULONG refcount, expected_refcount;
2364 IDXGIDevice *device;
2365 HRESULT hr;
2366 IDXGIDevice *test_object;
2367 IUnknown *ptr;
2368 static const DWORD data[] = {1, 2, 3, 4};
2369 UINT size;
2370 static const GUID dxgi_private_data_test_guid =
2372 0xfdb37466,
2373 0x428f,
2374 0x4edf,
2375 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
2377 static const GUID dxgi_private_data_test_guid2 =
2379 0x2e5afac2,
2380 0x87b5,
2381 0x4c10,
2382 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
2385 if (!(device = create_device(0)))
2387 skip("Failed to create device, skipping tests.\n");
2388 return;
2391 test_object = create_device(0);
2393 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
2394 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
2395 * NULL interface is not considered a clear but as setting an interface pointer that
2396 * happens to be NULL. */
2397 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 0, NULL);
2398 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2399 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2400 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2401 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2402 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2403 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, ~0U, NULL);
2404 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2406 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2407 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2408 size = sizeof(ptr) * 2;
2409 ptr = (IUnknown *)0xdeadbeef;
2410 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2411 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2412 ok(!ptr, "Got unexpected pointer %p.\n", ptr);
2413 ok(size == sizeof(IUnknown *), "Got unexpected size %u.\n", size);
2415 refcount = get_refcount((IUnknown *)test_object);
2416 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2417 (IUnknown *)test_object);
2418 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2419 expected_refcount = refcount + 1;
2420 refcount = get_refcount((IUnknown *)test_object);
2421 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2422 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2423 (IUnknown *)test_object);
2424 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2425 refcount = get_refcount((IUnknown *)test_object);
2426 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2428 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid, NULL);
2429 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2430 expected_refcount--;
2431 refcount = get_refcount((IUnknown *)test_object);
2432 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2434 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2435 (IUnknown *)test_object);
2436 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2437 size = sizeof(data);
2438 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, size, data);
2439 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2440 refcount = get_refcount((IUnknown *)test_object);
2441 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2442 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2443 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2444 hr = IDXGIDevice_SetPrivateData(device, &dxgi_private_data_test_guid, 42, NULL);
2445 ok(hr == S_FALSE, "Got unexpected hr %#x.\n", hr);
2447 hr = IDXGIDevice_SetPrivateDataInterface(device, &dxgi_private_data_test_guid,
2448 (IUnknown *)test_object);
2449 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2450 expected_refcount++;
2451 size = 2 * sizeof(ptr);
2452 ptr = NULL;
2453 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2454 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2455 ok(size == sizeof(test_object), "Got unexpected size %u.\n", size);
2456 expected_refcount++;
2457 refcount = get_refcount((IUnknown *)test_object);
2458 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2459 if (ptr)
2460 IUnknown_Release(ptr);
2461 expected_refcount--;
2463 ptr = (IUnknown *)0xdeadbeef;
2464 size = 1;
2465 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2466 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2467 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2468 size = 2 * sizeof(ptr);
2469 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, NULL);
2470 ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
2471 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2472 refcount = get_refcount((IUnknown *)test_object);
2473 ok(refcount == expected_refcount, "Got unexpected refcount %u, expected %u.\n", refcount, expected_refcount);
2475 size = 1;
2476 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, &size, &ptr);
2477 ok(hr == DXGI_ERROR_MORE_DATA, "Got unexpected hr %#x.\n", hr);
2478 ok(size == sizeof(device), "Got unexpected size %u.\n", size);
2479 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2480 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, NULL, NULL);
2481 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2482 size = 0xdeadbabe;
2483 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid2, &size, &ptr);
2484 ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
2485 ok(size == 0, "Got unexpected size %u.\n", size);
2486 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2487 hr = IDXGIDevice_GetPrivateData(device, &dxgi_private_data_test_guid, NULL, &ptr);
2488 ok(hr == E_INVALIDARG, "Got unexpected hr %#x.\n", hr);
2489 ok(ptr == (IUnknown *)0xdeadbeef, "Got unexpected pointer %p.\n", ptr);
2491 refcount = IDXGIDevice_Release(device);
2492 ok(!refcount, "Device has %u references left.\n", refcount);
2493 refcount = IDXGIDevice_Release(test_object);
2494 ok(!refcount, "Test object has %u references left.\n", refcount);
2497 static void test_swapchain_resize(void)
2499 DXGI_SWAP_CHAIN_DESC swapchain_desc;
2500 D3D10_TEXTURE2D_DESC texture_desc;
2501 DXGI_SURFACE_DESC surface_desc;
2502 IDXGISwapChain *swapchain;
2503 ID3D10Texture2D *texture;
2504 IDXGISurface *surface;
2505 IDXGIAdapter *adapter;
2506 IDXGIFactory *factory;
2507 IDXGIDevice *device;
2508 RECT client_rect, r;
2509 ULONG refcount;
2510 HWND window;
2511 HRESULT hr;
2512 BOOL ret;
2514 if (!(device = create_device(0)))
2516 skip("Failed to create device, skipping tests.\n");
2517 return;
2519 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2520 0, 0, 640, 480, NULL, NULL, NULL, NULL);
2521 ret = GetClientRect(window, &client_rect);
2522 ok(ret, "Failed to get client rect.\n");
2524 hr = IDXGIDevice_GetAdapter(device, &adapter);
2525 ok(SUCCEEDED(hr), "Failed to get adapter, hr %#x.\n", hr);
2526 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2527 ok(SUCCEEDED(hr), "Failed to get factory, hr %#x.\n", hr);
2528 IDXGIAdapter_Release(adapter);
2530 swapchain_desc.BufferDesc.Width = 640;
2531 swapchain_desc.BufferDesc.Height = 480;
2532 swapchain_desc.BufferDesc.RefreshRate.Numerator = 60;
2533 swapchain_desc.BufferDesc.RefreshRate.Denominator = 1;
2534 swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2535 swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
2536 swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
2537 swapchain_desc.SampleDesc.Count = 1;
2538 swapchain_desc.SampleDesc.Quality = 0;
2539 swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2540 swapchain_desc.BufferCount = 1;
2541 swapchain_desc.OutputWindow = window;
2542 swapchain_desc.Windowed = TRUE;
2543 swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
2544 swapchain_desc.Flags = 0;
2546 hr = IDXGIFactory_CreateSwapChain(factory, (IUnknown *)device, &swapchain_desc, &swapchain);
2547 ok(SUCCEEDED(hr), "Failed to create swapchain, hr %#x.\n", hr);
2548 IDXGIFactory_Release(factory);
2549 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2550 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2551 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2552 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2554 ret = GetClientRect(window, &r);
2555 ok(ret, "Failed to get client rect.\n");
2556 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2557 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2559 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2560 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2561 ok(swapchain_desc.BufferDesc.Width == 640,
2562 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2563 ok(swapchain_desc.BufferDesc.Height == 480,
2564 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2565 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2566 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2567 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2568 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2569 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2570 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2571 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2572 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2573 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2574 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2575 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2576 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2577 ok(swapchain_desc.SampleDesc.Count == 1,
2578 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2579 ok(!swapchain_desc.SampleDesc.Quality,
2580 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2581 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2582 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2583 ok(swapchain_desc.BufferCount == 1,
2584 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2585 ok(swapchain_desc.OutputWindow == window,
2586 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2587 ok(swapchain_desc.Windowed,
2588 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2589 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2590 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2591 ok(!swapchain_desc.Flags,
2592 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2594 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2595 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2596 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2597 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2598 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2599 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2600 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2602 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2603 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2604 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2605 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2606 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2607 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2608 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2609 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2610 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2611 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2612 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2613 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2615 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2616 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
2618 ret = GetClientRect(window, &r);
2619 ok(ret, "Failed to get client rect.\n");
2620 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2621 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2623 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2624 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2625 ok(swapchain_desc.BufferDesc.Width == 640,
2626 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2627 ok(swapchain_desc.BufferDesc.Height == 480,
2628 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2629 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2630 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2631 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2632 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2633 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2634 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2635 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM,
2636 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2637 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2638 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2639 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2640 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2641 ok(swapchain_desc.SampleDesc.Count == 1,
2642 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2643 ok(!swapchain_desc.SampleDesc.Quality,
2644 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2645 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2646 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2647 ok(swapchain_desc.BufferCount == 1,
2648 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2649 ok(swapchain_desc.OutputWindow == window,
2650 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2651 ok(swapchain_desc.Windowed,
2652 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2653 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2654 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2655 ok(!swapchain_desc.Flags,
2656 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2658 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2659 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2660 ok(surface_desc.Width == 640, "Got unexpected Width %u.\n", surface_desc.Width);
2661 ok(surface_desc.Height == 480, "Got unexpected Height %u.\n", surface_desc.Height);
2662 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", surface_desc.Format);
2663 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2664 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2666 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2667 ok(texture_desc.Width == 640, "Got unexpected Width %u.\n", texture_desc.Width);
2668 ok(texture_desc.Height == 480, "Got unexpected Height %u.\n", texture_desc.Height);
2669 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2670 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2671 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM, "Got unexpected Format %#x.\n", texture_desc.Format);
2672 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2673 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2674 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2675 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2676 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2677 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2679 ID3D10Texture2D_Release(texture);
2680 IDXGISurface_Release(surface);
2681 hr = IDXGISwapChain_ResizeBuffers(swapchain, 1, 320, 240, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 0);
2682 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
2683 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGISurface, (void **)&surface);
2684 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2685 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_ID3D10Texture2D, (void **)&texture);
2686 ok(SUCCEEDED(hr), "Failed to get buffer, hr %#x.\n", hr);
2688 ret = GetClientRect(window, &r);
2689 ok(ret, "Failed to get client rect.\n");
2690 ok(EqualRect(&r, &client_rect), "Got unexpected rect %s, expected %s.\n",
2691 wine_dbgstr_rect(&r), wine_dbgstr_rect(&client_rect));
2693 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2694 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2695 ok(swapchain_desc.BufferDesc.Width == 320,
2696 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc.BufferDesc.Width);
2697 ok(swapchain_desc.BufferDesc.Height == 240,
2698 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc.BufferDesc.Height);
2699 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2700 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2701 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2702 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2703 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2704 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2705 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
2706 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2707 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2708 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2709 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2710 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2711 ok(swapchain_desc.SampleDesc.Count == 1,
2712 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2713 ok(!swapchain_desc.SampleDesc.Quality,
2714 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2715 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2716 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2717 ok(swapchain_desc.BufferCount == 1,
2718 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2719 ok(swapchain_desc.OutputWindow == window,
2720 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2721 ok(swapchain_desc.Windowed,
2722 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2723 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2724 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2725 ok(!swapchain_desc.Flags,
2726 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2728 hr = IDXGISurface_GetDesc(surface, &surface_desc);
2729 ok(SUCCEEDED(hr), "Failed to get surface desc, hr %#x.\n", hr);
2730 ok(surface_desc.Width == 320, "Got unexpected Width %u.\n", surface_desc.Width);
2731 ok(surface_desc.Height == 240, "Got unexpected Height %u.\n", surface_desc.Height);
2732 ok(surface_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", surface_desc.Format);
2733 ok(surface_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", surface_desc.SampleDesc.Count);
2734 ok(!surface_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", surface_desc.SampleDesc.Quality);
2736 ID3D10Texture2D_GetDesc(texture, &texture_desc);
2737 ok(texture_desc.Width == 320, "Got unexpected Width %u.\n", texture_desc.Width);
2738 ok(texture_desc.Height == 240, "Got unexpected Height %u.\n", texture_desc.Height);
2739 ok(texture_desc.MipLevels == 1, "Got unexpected MipLevels %u.\n", texture_desc.MipLevels);
2740 ok(texture_desc.ArraySize == 1, "Got unexpected ArraySize %u.\n", texture_desc.ArraySize);
2741 ok(texture_desc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "Got unexpected Format %#x.\n", texture_desc.Format);
2742 ok(texture_desc.SampleDesc.Count == 1, "Got unexpected SampleDesc.Count %u.\n", texture_desc.SampleDesc.Count);
2743 ok(!texture_desc.SampleDesc.Quality, "Got unexpected SampleDesc.Quality %u.\n", texture_desc.SampleDesc.Quality);
2744 ok(texture_desc.Usage == D3D10_USAGE_DEFAULT, "Got unexpected Usage %#x.\n", texture_desc.Usage);
2745 ok(texture_desc.BindFlags == D3D10_BIND_RENDER_TARGET, "Got unexpected BindFlags %#x.\n", texture_desc.BindFlags);
2746 ok(!texture_desc.CPUAccessFlags, "Got unexpected CPUAccessFlags %#x.\n", texture_desc.CPUAccessFlags);
2747 ok(!texture_desc.MiscFlags, "Got unexpected MiscFlags %#x.\n", texture_desc.MiscFlags);
2749 ID3D10Texture2D_Release(texture);
2750 IDXGISurface_Release(surface);
2752 hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
2753 ok(SUCCEEDED(hr), "Failed to resize buffers, hr %#x.\n", hr);
2755 hr = IDXGISwapChain_GetDesc(swapchain, &swapchain_desc);
2756 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2757 ok(swapchain_desc.BufferDesc.Width == client_rect.right - client_rect.left,
2758 "Got unexpected BufferDesc.Width %u, expected %u.\n",
2759 swapchain_desc.BufferDesc.Width, client_rect.right - client_rect.left);
2760 ok(swapchain_desc.BufferDesc.Height == client_rect.bottom - client_rect.top,
2761 "Got unexpected bufferDesc.Height %u, expected %u.\n",
2762 swapchain_desc.BufferDesc.Height, client_rect.bottom - client_rect.top);
2763 ok(swapchain_desc.BufferDesc.RefreshRate.Numerator == 60,
2764 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
2765 swapchain_desc.BufferDesc.RefreshRate.Numerator);
2766 ok(swapchain_desc.BufferDesc.RefreshRate.Denominator == 1,
2767 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
2768 swapchain_desc.BufferDesc.RefreshRate.Denominator);
2769 ok(swapchain_desc.BufferDesc.Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
2770 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc.BufferDesc.Format);
2771 ok(swapchain_desc.BufferDesc.ScanlineOrdering == DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED,
2772 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc.BufferDesc.ScanlineOrdering);
2773 ok(swapchain_desc.BufferDesc.Scaling == DXGI_MODE_SCALING_UNSPECIFIED,
2774 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc.BufferDesc.Scaling);
2775 ok(swapchain_desc.SampleDesc.Count == 1,
2776 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc.SampleDesc.Count);
2777 ok(!swapchain_desc.SampleDesc.Quality,
2778 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc.SampleDesc.Quality);
2779 ok(swapchain_desc.BufferUsage == DXGI_USAGE_RENDER_TARGET_OUTPUT,
2780 "Got unexpected BufferUsage %#x.\n", swapchain_desc.BufferUsage);
2781 ok(swapchain_desc.BufferCount == 1,
2782 "Got unexpected BufferCount %u.\n", swapchain_desc.BufferCount);
2783 ok(swapchain_desc.OutputWindow == window,
2784 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc.OutputWindow, window);
2785 ok(swapchain_desc.Windowed,
2786 "Got unexpected Windowed %#x.\n", swapchain_desc.Windowed);
2787 ok(swapchain_desc.SwapEffect == DXGI_SWAP_EFFECT_DISCARD,
2788 "Got unexpected SwapEffect %#x.\n", swapchain_desc.SwapEffect);
2789 ok(!swapchain_desc.Flags,
2790 "Got unexpected Flags %#x.\n", swapchain_desc.Flags);
2792 IDXGISwapChain_Release(swapchain);
2793 refcount = IDXGIDevice_Release(device);
2794 ok(!refcount, "Device has %u references left.\n", refcount);
2795 DestroyWindow(window);
2798 static void test_swapchain_parameters(void)
2800 IDXGISwapChain *swapchain;
2801 IUnknown *obj;
2802 IDXGIAdapter *adapter;
2803 IDXGIFactory *factory;
2804 IDXGIDevice *device;
2805 IDXGIResource *resource;
2806 DXGI_SWAP_CHAIN_DESC desc;
2807 HRESULT hr;
2808 unsigned int i, j;
2809 ULONG refcount;
2810 DXGI_USAGE usage, expected_usage, broken_usage;
2811 HWND window;
2812 static const struct
2814 BOOL windowed;
2815 UINT buffer_count;
2816 DXGI_SWAP_EFFECT swap_effect;
2817 HRESULT hr, vista_hr;
2818 UINT highest_accessible_buffer;
2820 tests[] =
2822 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2823 {TRUE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2824 {TRUE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2825 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2826 {TRUE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
2827 {TRUE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
2828 {TRUE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
2829 {TRUE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2830 {TRUE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2831 {TRUE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2832 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2833 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2834 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
2835 {TRUE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
2836 {TRUE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2837 {TRUE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2838 {TRUE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2839 {TRUE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2840 {TRUE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2841 {TRUE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2842 {TRUE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2843 {TRUE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
2844 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
2845 {TRUE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2846 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2847 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2848 {TRUE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2849 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2851 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2852 {FALSE, 1, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2853 {FALSE, 2, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2854 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2855 {FALSE, 1, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 0},
2856 {FALSE, 2, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 1},
2857 {FALSE, 3, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 2},
2858 {FALSE, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2859 {FALSE, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2860 {FALSE, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2861 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2862 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2863 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 1},
2864 {FALSE, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 2},
2865 {FALSE, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2866 {FALSE, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2867 {FALSE, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2868 {FALSE, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2869 {FALSE, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2870 {FALSE, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2871 {FALSE, 16, DXGI_SWAP_EFFECT_DISCARD, S_OK, S_OK, 0},
2872 {FALSE, 16, DXGI_SWAP_EFFECT_SEQUENTIAL, S_OK, S_OK, 15},
2873 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, S_OK, DXGI_ERROR_INVALID_CALL, 15},
2874 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
2875 * process. Disable it for now.
2876 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
2878 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2879 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2880 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2881 {FALSE, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
2884 if (!(device = create_device(0)))
2886 skip("Failed to create device, skipping tests.\n");
2887 return;
2889 window = CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
2890 0, 0, 640, 480, 0, 0, 0, 0);
2892 hr = IDXGIDevice_QueryInterface(device, &IID_IUnknown, (void **)&obj);
2893 ok(SUCCEEDED(hr), "IDXGIDevice does not implement IUnknown\n");
2895 hr = IDXGIDevice_GetAdapter(device, &adapter);
2896 ok(SUCCEEDED(hr), "GetAdapter failed, hr %#x.\n", hr);
2898 hr = IDXGIAdapter_GetParent(adapter, &IID_IDXGIFactory, (void **)&factory);
2899 ok(SUCCEEDED(hr), "GetParent failed, hr %#x.\n", hr);
2901 for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
2903 memset(&desc, 0, sizeof(desc));
2904 desc.BufferDesc.Width = registry_mode.dmPelsWidth;
2905 desc.BufferDesc.Height = registry_mode.dmPelsHeight;
2906 desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
2907 desc.SampleDesc.Count = 1;
2908 desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
2909 desc.OutputWindow = window;
2911 desc.Windowed = tests[i].windowed;
2912 desc.BufferCount = tests[i].buffer_count;
2913 desc.SwapEffect = tests[i].swap_effect;
2915 hr = IDXGIFactory_CreateSwapChain(factory, obj, &desc, &swapchain);
2916 ok(hr == tests[i].hr || broken(hr == tests[i].vista_hr)
2917 || (SUCCEEDED(tests[i].hr) && hr == DXGI_STATUS_OCCLUDED),
2918 "Got unexpected hr %#x, test %u.\n", hr, i);
2919 if (FAILED(hr))
2920 continue;
2922 hr = IDXGISwapChain_GetBuffer(swapchain, 0, &IID_IDXGIResource, (void **)&resource);
2923 todo_wine ok(SUCCEEDED(hr), "GetBuffer(0) failed, hr %#x, test %u.\n", hr, i);
2924 if (FAILED(hr))
2926 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2927 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2929 IDXGISwapChain_Release(swapchain);
2930 continue;
2933 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
2934 if (tests[i].swap_effect == DXGI_SWAP_EFFECT_DISCARD)
2935 expected_usage |= DXGI_USAGE_DISCARD_ON_PRESENT;
2936 hr = IDXGIResource_GetUsage(resource, &usage);
2937 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u.\n", hr, i);
2938 ok(usage == expected_usage, "Got usage %x, expected %x, test %u.\n", usage, expected_usage, i);
2940 IDXGIResource_Release(resource);
2942 hr = IDXGISwapChain_GetDesc(swapchain, &desc);
2943 ok(SUCCEEDED(hr), "Failed to get swapchain desc, hr %#x.\n", hr);
2945 for (j = 1; j <= tests[i].highest_accessible_buffer; j++)
2947 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
2948 ok(SUCCEEDED(hr), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr, i, j);
2950 /* Buffers > 0 are supposed to be read only. This is the case except that in
2951 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
2952 * writable. This is not the case if an unsupported refresh rate is passed
2953 * for some reason, probably because the invalid refresh rate triggers a
2954 * kinda-sorta windowed mode.
2956 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
2957 * broken.
2959 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
2960 * the draw on the screen right away (Aero on or off doesn't matter), but
2961 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
2963 * Note that if the application doesn't have focused creating a fullscreen
2964 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
2965 * so use the Windowed property of the swapchain that was actually created. */
2966 expected_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_READ_ONLY;
2967 broken_usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER;
2969 if (desc.Windowed || j < tests[i].highest_accessible_buffer)
2970 broken_usage |= DXGI_USAGE_READ_ONLY;
2972 hr = IDXGIResource_GetUsage(resource, &usage);
2973 ok(SUCCEEDED(hr), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr, i, j);
2974 ok(usage == expected_usage || broken(usage == broken_usage),
2975 "Got usage %x, expected %x, test %u, buffer %u.\n",
2976 usage, expected_usage, i, j);
2978 IDXGIResource_Release(resource);
2980 hr = IDXGISwapChain_GetBuffer(swapchain, j, &IID_IDXGIResource, (void **)&resource);
2981 ok(hr == DXGI_ERROR_INVALID_CALL, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j, hr, i);
2983 hr = IDXGISwapChain_SetFullscreenState(swapchain, FALSE, NULL);
2984 ok(SUCCEEDED(hr), "SetFullscreenState failed, hr %#x.\n", hr);
2986 IDXGISwapChain_Release(swapchain);
2989 IDXGIFactory_Release(factory);
2990 IDXGIAdapter_Release(adapter);
2991 IUnknown_Release(obj);
2992 refcount = IDXGIDevice_Release(device);
2993 ok(!refcount, "Device has %u references left.\n", refcount);
2994 DestroyWindow(window);
2997 static void test_maximum_frame_latency(void)
2999 IDXGIDevice1 *device1;
3000 IDXGIDevice *device;
3001 UINT max_latency;
3002 ULONG refcount;
3003 HRESULT hr;
3005 if (!(device = create_device(0)))
3007 skip("Failed to create device.\n");
3008 return;
3011 if (SUCCEEDED(IDXGIDevice_QueryInterface(device, &IID_IDXGIDevice1, (void **)&device1)))
3013 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3014 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3015 ok(max_latency == DEFAULT_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3017 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY);
3018 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3019 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3020 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3021 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3023 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, MAX_FRAME_LATENCY + 1);
3024 ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
3025 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3026 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3027 todo_wine ok(max_latency == MAX_FRAME_LATENCY, "Got unexpected maximum frame latency %u.\n", max_latency);
3029 hr = IDXGIDevice1_SetMaximumFrameLatency(device1, 0);
3030 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3031 hr = IDXGIDevice1_GetMaximumFrameLatency(device1, &max_latency);
3032 todo_wine ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
3033 /* 0 does not reset to the default frame latency on all Windows versions. */
3034 ok(max_latency == DEFAULT_FRAME_LATENCY || broken(!max_latency),
3035 "Got unexpected maximum frame latency %u.\n", max_latency);
3037 IDXGIDevice1_Release(device1);
3039 else
3041 win_skip("IDXGIDevice1 is not implemented.\n");
3044 refcount = IDXGIDevice_Release(device);
3045 ok(!refcount, "Device has %u references left.\n", refcount);
3048 static void test_output_desc(void)
3050 IDXGIAdapter *adapter, *adapter2;
3051 IDXGIOutput *output, *output2;
3052 DXGI_OUTPUT_DESC desc;
3053 IDXGIFactory *factory;
3054 unsigned int i, j;
3055 ULONG refcount;
3056 HRESULT hr;
3058 hr = CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory);
3059 ok(SUCCEEDED(hr), "Failed to create DXGI factory, hr %#x.\n", hr);
3061 for (i = 0; ; ++i)
3063 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter);
3064 if (hr == DXGI_ERROR_NOT_FOUND)
3065 break;
3066 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3068 hr = IDXGIFactory_EnumAdapters(factory, i, &adapter2);
3069 ok(SUCCEEDED(hr), "Failed to enumerate adapter %u, hr %#x.\n", i, hr);
3070 ok(adapter != adapter2, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter, adapter2);
3071 refcount = get_refcount((IUnknown *)adapter);
3072 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3073 IDXGIAdapter_Release(adapter2);
3075 refcount = get_refcount((IUnknown *)factory);
3076 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3077 refcount = get_refcount((IUnknown *)adapter);
3078 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3080 for (j = 0; ; ++j)
3082 MONITORINFOEXW monitor_info;
3083 BOOL ret;
3085 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output);
3086 if (hr == DXGI_ERROR_NOT_FOUND)
3087 break;
3088 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3090 hr = IDXGIAdapter_EnumOutputs(adapter, j, &output2);
3091 ok(SUCCEEDED(hr), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j, i, hr);
3092 ok(output != output2, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output, output2);
3093 refcount = get_refcount((IUnknown *)output);
3094 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3095 IDXGIOutput_Release(output2);
3097 refcount = get_refcount((IUnknown *)factory);
3098 ok(refcount == 2, "Get unexpected refcount %u.\n", refcount);
3099 refcount = get_refcount((IUnknown *)adapter);
3100 ok(refcount == 2, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3101 refcount = get_refcount((IUnknown *)output);
3102 ok(refcount == 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount, j, i);
3104 hr = IDXGIOutput_GetDesc(output, NULL);
3105 ok(hr == E_INVALIDARG, "Got unexpected hr %#x for output %u on adapter %u.\n", hr, j, i);
3106 hr = IDXGIOutput_GetDesc(output, &desc);
3107 ok(SUCCEEDED(hr), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j, i, hr);
3109 monitor_info.cbSize = sizeof(monitor_info);
3110 ret = GetMonitorInfoW(desc.Monitor, (MONITORINFO *)&monitor_info);
3111 ok(ret, "Failed to get monitor info.\n");
3112 ok(!lstrcmpW(desc.DeviceName, monitor_info.szDevice), "Got unexpected device name %s, expected %s.\n",
3113 wine_dbgstr_w(desc.DeviceName), wine_dbgstr_w(monitor_info.szDevice));
3114 ok(EqualRect(&desc.DesktopCoordinates, &monitor_info.rcMonitor),
3115 "Got unexpected desktop coordinates %s, expected %s.\n",
3116 wine_dbgstr_rect(&desc.DesktopCoordinates),
3117 wine_dbgstr_rect(&monitor_info.rcMonitor));
3119 IDXGIOutput_Release(output);
3120 refcount = get_refcount((IUnknown *)adapter);
3121 ok(refcount == 1, "Get unexpected refcount %u for adapter %u.\n", refcount, i);
3124 IDXGIAdapter_Release(adapter);
3125 refcount = get_refcount((IUnknown *)factory);
3126 ok(refcount == 1, "Get unexpected refcount %u.\n", refcount);
3129 refcount = IDXGIFactory_Release(factory);
3130 ok(!refcount, "IDXGIFactory has %u references left.\n", refcount);
3133 START_TEST(device)
3135 pCreateDXGIFactory1 = (void *)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
3137 registry_mode.dmSize = sizeof(registry_mode);
3138 ok(EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &registry_mode), "Failed to get display mode.\n");
3140 test_adapter_desc();
3141 test_check_interface_support();
3142 test_create_surface();
3143 test_parents();
3144 test_output();
3145 test_find_closest_matching_mode();
3146 test_create_swapchain();
3147 test_get_containing_output();
3148 test_set_fullscreen();
3149 test_default_fullscreen_target_output();
3150 test_resize_target();
3151 test_inexact_modes();
3152 test_create_factory();
3153 test_private_data();
3154 test_swapchain_resize();
3155 test_swapchain_parameters();
3156 test_maximum_frame_latency();
3157 test_output_desc();