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
23 #include "wine/test.h"
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
;
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
;
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
))
138 struct fullscreen_state
146 struct swapchain_fullscreen_state
148 struct fullscreen_state fullscreen_state
;
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
;
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
, ¤t_state
, window
);
197 check_fullscreen_state_(line
, ¤t_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
;
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
;
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",
243 IDXGIOutput_Release(target
);
244 IDXGIOutput_Release(containing_output
);
245 IDXGIAdapter_Release(adapter
);
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
)
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
;
269 DXGI_MODE_DESC mode_desc
= swapchain_desc
->BufferDesc
;
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
;
295 state
->target
= target
;
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
;
312 if (SUCCEEDED(D3D10CreateDevice1(NULL
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
313 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
)))
315 if (SUCCEEDED(D3D10CreateDevice1(NULL
, D3D10_DRIVER_TYPE_WARP
, NULL
,
316 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
)))
318 if (SUCCEEDED(D3D10CreateDevice1(NULL
, D3D10_DRIVER_TYPE_REFERENCE
, NULL
,
319 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
)))
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
);
332 static void test_adapter_desc(void)
334 DXGI_ADAPTER_DESC1 desc1
;
335 IDXGIAdapter1
*adapter1
;
336 DXGI_ADAPTER_DESC desc
;
337 IDXGIAdapter
*adapter
;
342 if (!(device
= create_device(0)))
344 skip("Failed to create device, skipping tests.\n");
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",
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
)
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
);
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
;
410 if (!(device
= create_device(0)))
412 skip("Failed to create device.\n");
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
);
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
);
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
;
465 if (!(device
= create_device(0)))
467 skip("Failed to create device, skipping tests.\n");
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
;
511 if (!(device
= create_device(0)))
513 skip("Failed to create device, skipping tests.\n");
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");
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
;
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");
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
);
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
);
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
);
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");
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");
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
);
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);
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
;
686 if (!(device
= create_device(0)))
688 skip("Failed to create device.\n");
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
);
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");
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
)
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
);
740 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
741 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
745 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
746 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
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
);
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
);
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. */
805 for (i
= 0; i
< mode_count
; ++i
)
807 if (mode
.Width
>= modes
[i
].Width
&& mode
.Height
>= modes
[i
].Height
)
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
);
851 IDXGIOutput_Release(output
);
852 IDXGIAdapter_Release(adapter
);
853 refcount
= IDXGIDevice_Release(device
);
854 ok(!refcount
, "Device has %u references left.\n", refcount
);
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
;
882 const struct refresh_rates refresh_list
[] =
884 {60, 60, FALSE
, FALSE
},
885 {60, 0, TRUE
, FALSE
},
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");
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
);
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
);
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
);
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
);
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
);
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
;
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
);
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");
1197 if (result_desc
.Windowed
)
1199 win_skip("Fullscreen not supported.\n");
1200 IDXGIOutput_Release(expected_state
.target
);
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
);
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
;
1283 if (!(device
= create_device(0)))
1285 skip("Failed to create device.\n");
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;
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
);
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
);
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
));
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
);
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
[] =
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},
1403 x
= output_desc
.DesktopCoordinates
.left
;
1404 y
= output_desc
.DesktopCoordinates
.top
;
1407 x
= output_desc
.DesktopCoordinates
.right
;
1408 y
= output_desc
.DesktopCoordinates
.top
;
1411 x
= output_desc
.DesktopCoordinates
.right
;
1412 y
= output_desc
.DesktopCoordinates
.bottom
;
1415 x
= output_desc
.DesktopCoordinates
.left
;
1416 y
= output_desc
.DesktopCoordinates
.bottom
;
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
);
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
;
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
;
1516 while (IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
) != DXGI_ERROR_NOT_FOUND
)
1518 IDXGIOutput_Release(output
);
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
;
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
);
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
);
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
);
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
;
1637 if (!(device
= create_device(0)))
1639 skip("Failed to create device.\n");
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
);
1676 skip("Could not change fullscreen state.\n");
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
);
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
;
1730 if (!(device
= create_device(0)))
1732 skip("Failed to create device.\n");
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
);
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
);
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
);
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
);
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
;
1849 unsigned int width
, height
;
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
));
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
;
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
);
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
)
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
;
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");
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);
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
);
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
);
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
;
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
;
2138 unsigned int width
, height
;
2147 if (!(device
= create_device(0)))
2149 skip("Failed to create device.\n");
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");
2194 if (result_desc
.Windowed
)
2196 win_skip("Fullscreen not supported.\n");
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
);
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
;
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");
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
;
2366 IDXGIDevice
*test_object
;
2368 static const DWORD data
[] = {1, 2, 3, 4};
2370 static const GUID dxgi_private_data_test_guid
=
2375 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
2377 static const GUID dxgi_private_data_test_guid2
=
2382 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
2385 if (!(device
= create_device(0)))
2387 skip("Failed to create device, skipping tests.\n");
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
);
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
);
2460 IUnknown_Release(ptr
);
2461 expected_refcount
--;
2463 ptr
= (IUnknown
*)0xdeadbeef;
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
);
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
);
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
;
2514 if (!(device
= create_device(0)))
2516 skip("Failed to create device, skipping tests.\n");
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
;
2802 IDXGIAdapter
*adapter
;
2803 IDXGIFactory
*factory
;
2804 IDXGIDevice
*device
;
2805 IDXGIResource
*resource
;
2806 DXGI_SWAP_CHAIN_DESC desc
;
2810 DXGI_USAGE usage
, expected_usage
, broken_usage
;
2816 DXGI_SWAP_EFFECT swap_effect
;
2817 HRESULT hr
, vista_hr
;
2818 UINT highest_accessible_buffer
;
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");
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
);
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
);
2926 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2927 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
2929 IDXGISwapChain_Release(swapchain
);
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
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
;
3005 if (!(device
= create_device(0)))
3007 skip("Failed to create device.\n");
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
);
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
;
3058 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
3059 ok(SUCCEEDED(hr
), "Failed to create DXGI factory, hr %#x.\n", hr
);
3063 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter
);
3064 if (hr
== DXGI_ERROR_NOT_FOUND
)
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
);
3082 MONITORINFOEXW monitor_info
;
3085 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output
);
3086 if (hr
== DXGI_ERROR_NOT_FOUND
)
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
);
3135 pCreateDXGIFactory1
= (void *)GetProcAddress(GetModuleHandleA("dxgi.dll"), "CreateDXGIFactory1");
3137 registry_mode
.dmSize
= sizeof(registry_mode
);
3138 ok(EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, ®istry_mode
), "Failed to get display mode.\n");
3140 test_adapter_desc();
3141 test_check_interface_support();
3142 test_create_surface();
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();