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
21 #define WIN32_NO_STATUS
27 #include "d3d12sdklayers.h"
29 #include "ddk/d3dkmthk.h"
30 #include "wine/heap.h"
31 #include "wine/test.h"
35 DEFAULT_FRAME_LATENCY
= 3,
36 MAX_FRAME_LATENCY
= 16,
39 static DEVMODEW registry_mode
;
41 static HRESULT (WINAPI
*pCreateDXGIFactory1
)(REFIID iid
, void **factory
);
42 static HRESULT (WINAPI
*pCreateDXGIFactory2
)(UINT flags
, REFIID iid
, void **factory
);
44 static NTSTATUS (WINAPI
*pD3DKMTCheckVidPnExclusiveOwnership
)(const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP
*desc
);
45 static NTSTATUS (WINAPI
*pD3DKMTCloseAdapter
)(const D3DKMT_CLOSEADAPTER
*desc
);
46 static NTSTATUS (WINAPI
*pD3DKMTOpenAdapterFromGdiDisplayName
)(D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME
*desc
);
48 static HRESULT (WINAPI
*pD3D11CreateDevice
)(IDXGIAdapter
*adapter
, D3D_DRIVER_TYPE driver_type
, HMODULE swrast
, UINT flags
,
49 const D3D_FEATURE_LEVEL
*feature_levels
, UINT levels
, UINT sdk_version
, ID3D11Device
**device_out
,
50 D3D_FEATURE_LEVEL
*obtained_feature_level
, ID3D11DeviceContext
**immediate_context
);
52 static PFN_D3D12_CREATE_DEVICE pD3D12CreateDevice
;
53 static PFN_D3D12_GET_DEBUG_INTERFACE pD3D12GetDebugInterface
;
55 static unsigned int use_adapter_idx
;
56 static BOOL use_warp_adapter
;
57 static BOOL use_mt
= TRUE
;
59 static struct test_entry
63 size_t mt_tests_size
, mt_test_count
;
65 static void queue_test(void (*test
)(void))
67 if (mt_test_count
>= mt_tests_size
)
69 mt_tests_size
= max(16, mt_tests_size
* 2);
70 mt_tests
= heap_realloc(mt_tests
, mt_tests_size
* sizeof(*mt_tests
));
72 mt_tests
[mt_test_count
++].test
= test
;
75 static DWORD WINAPI
thread_func(void *ctx
)
79 while (*i
< mt_test_count
)
82 if (InterlockedCompareExchange(i
, j
+ 1, j
) == j
)
89 static void run_queued_tests(void)
91 unsigned int thread_count
, i
;
98 for (i
= 0; i
< mt_test_count
; ++i
)
107 thread_count
= si
.dwNumberOfProcessors
;
108 threads
= heap_calloc(thread_count
, sizeof(*threads
));
109 for (i
= 0, test_idx
= 0; i
< thread_count
; ++i
)
111 threads
[i
] = CreateThread(NULL
, 0, thread_func
, &test_idx
, 0, NULL
);
112 ok(!!threads
[i
], "Failed to create thread %u.\n", i
);
114 WaitForMultipleObjects(thread_count
, threads
, TRUE
, INFINITE
);
115 for (i
= 0; i
< thread_count
; ++i
)
117 CloseHandle(threads
[i
]);
122 static ULONG
get_refcount(void *iface
)
124 IUnknown
*unknown
= iface
;
125 IUnknown_AddRef(unknown
);
126 return IUnknown_Release(unknown
);
129 static void get_virtual_rect(RECT
*rect
)
131 rect
->left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
132 rect
->top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
133 rect
->right
= rect
->left
+ GetSystemMetrics(SM_CXVIRTUALSCREEN
);
134 rect
->bottom
= rect
->top
+ GetSystemMetrics(SM_CYVIRTUALSCREEN
);
137 static BOOL
equal_mode_rect(const DEVMODEW
*mode1
, const DEVMODEW
*mode2
)
139 return mode1
->dmPosition
.x
== mode2
->dmPosition
.x
140 && mode1
->dmPosition
.y
== mode2
->dmPosition
.y
141 && mode1
->dmPelsWidth
== mode2
->dmPelsWidth
142 && mode1
->dmPelsHeight
== mode2
->dmPelsHeight
;
145 /* Free original_modes after finished using it */
146 static BOOL
save_display_modes(DEVMODEW
**original_modes
, unsigned int *display_count
)
148 unsigned int number
, size
= 2, count
= 0, index
= 0;
149 DISPLAY_DEVICEW display_device
;
150 DEVMODEW
*modes
, *tmp
;
152 if (!(modes
= heap_alloc(size
* sizeof(*modes
))))
155 display_device
.cb
= sizeof(display_device
);
156 while (EnumDisplayDevicesW(NULL
, index
++, &display_device
, 0))
158 /* Skip software devices */
159 if (swscanf(display_device
.DeviceName
, L
"\\\\.\\DISPLAY%u", &number
) != 1)
162 if (!(display_device
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
))
168 if (!(tmp
= heap_realloc(modes
, size
* sizeof(*modes
))))
176 memset(&modes
[count
], 0, sizeof(modes
[count
]));
177 modes
[count
].dmSize
= sizeof(modes
[count
]);
178 if (!EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &modes
[count
]))
184 lstrcpyW(modes
[count
++].dmDeviceName
, display_device
.DeviceName
);
187 *original_modes
= modes
;
188 *display_count
= count
;
192 static BOOL
restore_display_modes(DEVMODEW
*modes
, unsigned int count
)
197 for (index
= 0; index
< count
; ++index
)
199 ret
= ChangeDisplaySettingsExW(modes
[index
].dmDeviceName
, &modes
[index
], NULL
,
200 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
201 if (ret
!= DISP_CHANGE_SUCCESSFUL
)
204 ret
= ChangeDisplaySettingsExW(NULL
, NULL
, NULL
, 0, NULL
);
205 return ret
== DISP_CHANGE_SUCCESSFUL
;
208 /* try to make sure pending X events have been processed before continuing */
209 static void flush_events(void)
215 time
= GetTickCount() + diff
;
218 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, 100, QS_ALLINPUT
) == WAIT_TIMEOUT
)
220 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
221 DispatchMessageA(&msg
);
222 diff
= time
- GetTickCount();
226 #define check_interface(a, b, c, d) check_interface_(__LINE__, a, b, c, d)
227 static HRESULT
check_interface_(unsigned int line
, void *iface
, REFIID iid
,
228 BOOL supported
, BOOL is_broken
)
230 HRESULT hr
, expected_hr
, broken_hr
;
231 IUnknown
*unknown
= iface
, *out
;
236 broken_hr
= E_NOINTERFACE
;
240 expected_hr
= E_NOINTERFACE
;
244 out
= (IUnknown
*)0xdeadbeef;
245 hr
= IUnknown_QueryInterface(unknown
, iid
, (void **)&out
);
246 ok_(__FILE__
, line
)(hr
== expected_hr
|| broken(is_broken
&& hr
== broken_hr
),
247 "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
249 IUnknown_Release(out
);
251 ok_(__FILE__
, line
)(!out
, "Got unexpected pointer %p.\n", out
);
255 static BOOL
is_flip_model(DXGI_SWAP_EFFECT swap_effect
)
257 return swap_effect
== DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
258 || swap_effect
== DXGI_SWAP_EFFECT_FLIP_DISCARD
;
261 static unsigned int check_multisample_quality_levels(IDXGIDevice
*dxgi_device
,
262 DXGI_FORMAT format
, unsigned int sample_count
)
264 ID3D10Device
*device
;
268 hr
= IDXGIDevice_QueryInterface(dxgi_device
, &IID_ID3D10Device
, (void **)&device
);
269 ok(hr
== S_OK
, "Failed to query ID3D10Device, hr %#x.\n", hr
);
270 hr
= ID3D10Device_CheckMultisampleQualityLevels(device
, format
, sample_count
, &levels
);
271 ok(hr
== S_OK
, "Failed to check multisample quality levels, hr %#x.\n", hr
);
272 ID3D10Device_Release(device
);
277 #define MODE_DESC_IGNORE_RESOLUTION 0x00000001u
278 #define MODE_DESC_IGNORE_REFRESH_RATE 0x00000002u
279 #define MODE_DESC_IGNORE_FORMAT 0x00000004u
280 #define MODE_DESC_IGNORE_SCANLINE_ORDERING 0x00000008u
281 #define MODE_DESC_IGNORE_SCALING 0x00000010u
282 #define MODE_DESC_IGNORE_EXACT_RESOLUTION 0x00000020u
284 #define MODE_DESC_CHECK_RESOLUTION (~MODE_DESC_IGNORE_RESOLUTION & ~MODE_DESC_IGNORE_EXACT_RESOLUTION)
285 #define MODE_DESC_CHECK_FORMAT (~MODE_DESC_IGNORE_FORMAT)
287 #define check_mode_desc(a, b, c) check_mode_desc_(__LINE__, a, b, c)
288 static void check_mode_desc_(unsigned int line
, const DXGI_MODE_DESC
*desc
,
289 const DXGI_MODE_DESC
*expected_desc
, unsigned int ignore_flags
)
291 if (!(ignore_flags
& MODE_DESC_IGNORE_RESOLUTION
))
293 if (ignore_flags
& MODE_DESC_IGNORE_EXACT_RESOLUTION
)
294 ok_(__FILE__
, line
)(desc
->Width
* desc
->Height
==
295 expected_desc
->Width
* expected_desc
->Height
,
296 "Got resolution %ux%u, expected %ux%u.\n",
297 desc
->Width
, desc
->Height
, expected_desc
->Width
, expected_desc
->Height
);
299 ok_(__FILE__
, line
)(desc
->Width
== expected_desc
->Width
&&
300 desc
->Height
== expected_desc
->Height
,
301 "Got resolution %ux%u, expected %ux%u.\n",
302 desc
->Width
, desc
->Height
, expected_desc
->Width
, expected_desc
->Height
);
304 if (!(ignore_flags
& MODE_DESC_IGNORE_REFRESH_RATE
))
306 ok_(__FILE__
, line
)(desc
->RefreshRate
.Numerator
== expected_desc
->RefreshRate
.Numerator
307 && desc
->RefreshRate
.Denominator
== expected_desc
->RefreshRate
.Denominator
,
308 "Got refresh rate %u / %u, expected %u / %u.\n",
309 desc
->RefreshRate
.Numerator
, desc
->RefreshRate
.Denominator
,
310 expected_desc
->RefreshRate
.Denominator
, expected_desc
->RefreshRate
.Denominator
);
312 if (!(ignore_flags
& MODE_DESC_IGNORE_FORMAT
))
314 ok_(__FILE__
, line
)(desc
->Format
== expected_desc
->Format
,
315 "Got format %#x, expected %#x.\n", desc
->Format
, expected_desc
->Format
);
317 if (!(ignore_flags
& MODE_DESC_IGNORE_SCANLINE_ORDERING
))
319 ok_(__FILE__
, line
)(desc
->ScanlineOrdering
== expected_desc
->ScanlineOrdering
,
320 "Got scanline ordering %#x, expected %#x.\n",
321 desc
->ScanlineOrdering
, expected_desc
->ScanlineOrdering
);
323 if (!(ignore_flags
& MODE_DESC_IGNORE_SCALING
))
325 ok_(__FILE__
, line
)(desc
->Scaling
== expected_desc
->Scaling
,
326 "Got scaling %#x, expected %#x.\n",
327 desc
->Scaling
, expected_desc
->Scaling
);
331 static BOOL
equal_luid(LUID a
, LUID b
)
333 return a
.LowPart
== b
.LowPart
&& a
.HighPart
== b
.HighPart
;
336 #define check_adapter_desc(a, b) check_adapter_desc_(__LINE__, a, b)
337 static void check_adapter_desc_(unsigned int line
, const DXGI_ADAPTER_DESC
*desc
,
338 const struct DXGI_ADAPTER_DESC
*expected_desc
)
340 ok_(__FILE__
, line
)(!lstrcmpW(desc
->Description
, expected_desc
->Description
),
341 "Got description %s, expected %s.\n",
342 wine_dbgstr_w(desc
->Description
), wine_dbgstr_w(expected_desc
->Description
));
343 ok_(__FILE__
, line
)(desc
->VendorId
== expected_desc
->VendorId
,
344 "Got vendor id %04x, expected %04x.\n",
345 desc
->VendorId
, expected_desc
->VendorId
);
346 ok_(__FILE__
, line
)(desc
->DeviceId
== expected_desc
->DeviceId
,
347 "Got device id %04x, expected %04x.\n",
348 desc
->DeviceId
, expected_desc
->DeviceId
);
349 ok_(__FILE__
, line
)(desc
->SubSysId
== expected_desc
->SubSysId
,
350 "Got subsys id %04x, expected %04x.\n",
351 desc
->SubSysId
, expected_desc
->SubSysId
);
352 ok_(__FILE__
, line
)(desc
->Revision
== expected_desc
->Revision
,
353 "Got revision %02x, expected %02x.\n",
354 desc
->Revision
, expected_desc
->Revision
);
355 ok_(__FILE__
, line
)(desc
->DedicatedVideoMemory
== expected_desc
->DedicatedVideoMemory
,
356 "Got dedicated video memory %lu, expected %lu.\n",
357 desc
->DedicatedVideoMemory
, expected_desc
->DedicatedVideoMemory
);
358 ok_(__FILE__
, line
)(desc
->DedicatedSystemMemory
== expected_desc
->DedicatedSystemMemory
,
359 "Got dedicated system memory %lu, expected %lu.\n",
360 desc
->DedicatedSystemMemory
, expected_desc
->DedicatedSystemMemory
);
361 ok_(__FILE__
, line
)(desc
->SharedSystemMemory
== expected_desc
->SharedSystemMemory
,
362 "Got shared system memory %lu, expected %lu.\n",
363 desc
->SharedSystemMemory
, expected_desc
->SharedSystemMemory
);
364 ok_(__FILE__
, line
)(equal_luid(desc
->AdapterLuid
, expected_desc
->AdapterLuid
),
365 "Got LUID %08x:%08x, expected %08x:%08x.\n",
366 desc
->AdapterLuid
.HighPart
, desc
->AdapterLuid
.LowPart
,
367 expected_desc
->AdapterLuid
.HighPart
, expected_desc
->AdapterLuid
.LowPart
);
370 #define check_output_desc(a, b) check_output_desc_(__LINE__, a, b)
371 static void check_output_desc_(unsigned int line
, const DXGI_OUTPUT_DESC
*desc
,
372 const struct DXGI_OUTPUT_DESC
*expected_desc
)
374 ok_(__FILE__
, line
)(!lstrcmpW(desc
->DeviceName
, expected_desc
->DeviceName
),
375 "Got unexpected device name %s, expected %s.\n",
376 wine_dbgstr_w(desc
->DeviceName
), wine_dbgstr_w(expected_desc
->DeviceName
));
377 ok_(__FILE__
, line
)(EqualRect(&desc
->DesktopCoordinates
, &expected_desc
->DesktopCoordinates
),
378 "Got unexpected desktop coordinates %s, expected %s.\n",
379 wine_dbgstr_rect(&desc
->DesktopCoordinates
),
380 wine_dbgstr_rect(&expected_desc
->DesktopCoordinates
));
383 #define check_output_equal(a, b) check_output_equal_(__LINE__, a, b)
384 static void check_output_equal_(unsigned int line
, IDXGIOutput
*output1
, IDXGIOutput
*output2
)
386 DXGI_OUTPUT_DESC desc1
, desc2
;
389 hr
= IDXGIOutput_GetDesc(output1
, &desc1
);
390 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
391 hr
= IDXGIOutput_GetDesc(output2
, &desc2
);
392 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
393 check_output_desc_(line
, &desc1
, &desc2
);
396 static BOOL
output_belongs_to_adapter(IDXGIOutput
*output
, IDXGIAdapter
*adapter
)
398 DXGI_OUTPUT_DESC output_desc
, desc
;
399 unsigned int output_idx
;
403 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
404 ok(SUCCEEDED(hr
), "Failed to get output desc, hr %#x.\n", hr
);
406 for (output_idx
= 0; IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &o
) != DXGI_ERROR_NOT_FOUND
; ++output_idx
)
408 hr
= IDXGIOutput_GetDesc(o
, &desc
);
409 ok(SUCCEEDED(hr
), "Failed to get output desc, hr %#x.\n", hr
);
410 IDXGIOutput_Release(o
);
412 if (!lstrcmpW(desc
.DeviceName
, output_desc
.DeviceName
)
413 && EqualRect(&desc
.DesktopCoordinates
, &output_desc
.DesktopCoordinates
))
420 struct fullscreen_state
430 struct swapchain_fullscreen_state
432 struct fullscreen_state fullscreen_state
;
437 #define capture_fullscreen_state(a, b) capture_fullscreen_state_(__LINE__, a, b)
438 static void capture_fullscreen_state_(unsigned int line
, struct fullscreen_state
*state
, HWND window
)
440 MONITORINFOEXW monitor_info
;
443 state
->style
= GetWindowLongA(window
, GWL_STYLE
);
444 state
->exstyle
= GetWindowLongA(window
, GWL_EXSTYLE
);
446 ret
= GetWindowRect(window
, &state
->window_rect
);
447 ok_(__FILE__
, line
)(ret
, "GetWindowRect failed.\n");
448 ret
= GetClientRect(window
, &state
->client_rect
);
449 ok_(__FILE__
, line
)(ret
, "GetClientRect failed.\n");
451 state
->monitor
= MonitorFromWindow(window
, MONITOR_DEFAULTTONULL
);
452 ok_(__FILE__
, line
)(!!state
->monitor
, "Failed to get monitor from window.\n");
454 monitor_info
.cbSize
= sizeof(monitor_info
);
455 ret
= GetMonitorInfoW(state
->monitor
, (MONITORINFO
*)&monitor_info
);
456 ok_(__FILE__
, line
)(ret
, "Failed to get monitor info.\n");
457 state
->monitor_rect
= monitor_info
.rcMonitor
;
460 static void check_fullscreen_state_(unsigned int line
, const struct fullscreen_state
*state
,
461 const struct fullscreen_state
*expected_state
, BOOL windowed
)
463 todo_wine_if(!windowed
)
464 ok_(__FILE__
, line
)((state
->style
& ~WS_VISIBLE
) == (expected_state
->style
& ~WS_VISIBLE
),
465 "Got style %#x, expected %#x.\n",
466 state
->style
& ~(DWORD
)WS_VISIBLE
, expected_state
->style
& ~(DWORD
)WS_VISIBLE
);
467 ok_(__FILE__
, line
)((state
->exstyle
& ~WS_EX_TOPMOST
) == (expected_state
->exstyle
& ~WS_EX_TOPMOST
),
468 "Got exstyle %#x, expected %#x.\n",
469 state
->exstyle
& ~(DWORD
)WS_EX_TOPMOST
, expected_state
->exstyle
& ~(DWORD
)WS_EX_TOPMOST
);
470 ok_(__FILE__
, line
)(EqualRect(&state
->window_rect
, &expected_state
->window_rect
),
471 "Got window rect %s, expected %s.\n",
472 wine_dbgstr_rect(&state
->window_rect
), wine_dbgstr_rect(&expected_state
->window_rect
));
473 ok_(__FILE__
, line
)(EqualRect(&state
->client_rect
, &expected_state
->client_rect
),
474 "Got client rect %s, expected %s.\n",
475 wine_dbgstr_rect(&state
->client_rect
), wine_dbgstr_rect(&expected_state
->client_rect
));
476 ok_(__FILE__
, line
)(state
->monitor
== expected_state
->monitor
,
477 "Got monitor %p, expected %p.\n",
478 state
->monitor
, expected_state
->monitor
);
479 ok_(__FILE__
, line
)(EqualRect(&state
->monitor_rect
, &expected_state
->monitor_rect
),
480 "Got monitor rect %s, expected %s.\n",
481 wine_dbgstr_rect(&state
->monitor_rect
), wine_dbgstr_rect(&expected_state
->monitor_rect
));
484 #define check_window_fullscreen_state(a, b) check_window_fullscreen_state_(__LINE__, a, b, TRUE)
485 static void check_window_fullscreen_state_(unsigned int line
, HWND window
,
486 const struct fullscreen_state
*expected_state
, BOOL windowed
)
488 struct fullscreen_state current_state
;
489 capture_fullscreen_state_(line
, ¤t_state
, window
);
490 check_fullscreen_state_(line
, ¤t_state
, expected_state
, windowed
);
493 #define check_swapchain_fullscreen_state(a, b) check_swapchain_fullscreen_state_(__LINE__, a, b)
494 static void check_swapchain_fullscreen_state_(unsigned int line
, IDXGISwapChain
*swapchain
,
495 const struct swapchain_fullscreen_state
*expected_state
)
497 IDXGIOutput
*containing_output
, *target
;
498 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
502 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
503 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
504 check_window_fullscreen_state_(line
, swapchain_desc
.OutputWindow
,
505 &expected_state
->fullscreen_state
, swapchain_desc
.Windowed
);
507 ok_(__FILE__
, line
)(swapchain_desc
.Windowed
== !expected_state
->fullscreen
,
508 "Got windowed %#x, expected %#x.\n",
509 swapchain_desc
.Windowed
, !expected_state
->fullscreen
);
511 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
512 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get fullscreen state, hr %#x.\n", hr
);
513 ok_(__FILE__
, line
)(fullscreen
== expected_state
->fullscreen
, "Got fullscreen %#x, expected %#x.\n",
514 fullscreen
, expected_state
->fullscreen
);
516 if (!swapchain_desc
.Windowed
&& expected_state
->fullscreen
)
518 IDXGIAdapter
*adapter
;
520 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
521 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get containing output, hr %#x.\n", hr
);
523 hr
= IDXGIOutput_GetParent(containing_output
, &IID_IDXGIAdapter
, (void **)&adapter
);
524 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
526 check_output_equal_(line
, target
, expected_state
->target
);
527 ok_(__FILE__
, line
)(target
== containing_output
, "Got target %p, expected %p.\n",
528 target
, containing_output
);
529 ok_(__FILE__
, line
)(output_belongs_to_adapter(target
, adapter
),
530 "Output %p doesn't belong to adapter %p.\n",
533 IDXGIOutput_Release(target
);
534 IDXGIOutput_Release(containing_output
);
535 IDXGIAdapter_Release(adapter
);
539 ok_(__FILE__
, line
)(!target
, "Got unexpected target %p.\n", target
);
543 #define compute_expected_swapchain_fullscreen_state_after_fullscreen_change(a, b, c, d, e, f) \
544 compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(__LINE__, a, b, c, d, e, f)
545 static void compute_expected_swapchain_fullscreen_state_after_fullscreen_change_(unsigned int line
,
546 struct swapchain_fullscreen_state
*state
, const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
,
547 const RECT
*old_monitor_rect
, unsigned int new_width
, unsigned int new_height
, IDXGIOutput
*target
)
549 if (!new_width
&& !new_height
)
552 GetClientRect(swapchain_desc
->OutputWindow
, &client_rect
);
553 new_width
= client_rect
.right
- client_rect
.left
;
554 new_height
= client_rect
.bottom
- client_rect
.top
;
559 DXGI_MODE_DESC mode_desc
= swapchain_desc
->BufferDesc
;
562 mode_desc
.Width
= new_width
;
563 mode_desc
.Height
= new_height
;
564 hr
= IDXGIOutput_FindClosestMatchingMode(target
, &mode_desc
, &mode_desc
, NULL
);
565 ok_(__FILE__
, line
)(SUCCEEDED(hr
), "FindClosestMatchingMode failed, hr %#x.\n", hr
);
566 new_width
= mode_desc
.Width
;
567 new_height
= mode_desc
.Height
;
570 state
->fullscreen_state
.style
&= WS_VISIBLE
| WS_CLIPSIBLINGS
;
571 state
->fullscreen_state
.exstyle
&= WS_EX_TOPMOST
;
573 state
->fullscreen
= TRUE
;
574 if (swapchain_desc
->Flags
& DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
)
576 unsigned int new_x
= (old_monitor_rect
->left
>= 0)
577 ? old_monitor_rect
->left
: old_monitor_rect
->right
- new_width
;
578 unsigned new_y
= (old_monitor_rect
->top
>= 0)
579 ? old_monitor_rect
->top
: old_monitor_rect
->bottom
- new_height
;
580 RECT new_monitor_rect
= {0, 0, new_width
, new_height
};
581 OffsetRect(&new_monitor_rect
, new_x
, new_y
);
583 SetRect(&state
->fullscreen_state
.client_rect
, 0, 0, new_width
, new_height
);
584 state
->fullscreen_state
.monitor_rect
= new_monitor_rect
;
585 state
->fullscreen_state
.window_rect
= new_monitor_rect
;
588 state
->target
= target
;
592 state
->fullscreen_state
.window_rect
= *old_monitor_rect
;
593 SetRect(&state
->fullscreen_state
.client_rect
, 0, 0,
594 old_monitor_rect
->right
- old_monitor_rect
->left
,
595 old_monitor_rect
->bottom
- old_monitor_rect
->top
);
599 #define wait_fullscreen_state(a, b, c) wait_fullscreen_state_(__LINE__, a, b, c)
600 static void wait_fullscreen_state_(unsigned int line
, IDXGISwapChain
*swapchain
, BOOL expected
, BOOL todo
)
602 static const unsigned int wait_timeout
= 2000;
603 static const unsigned int wait_step
= 100;
604 unsigned int total_time
= 0;
608 while (total_time
< wait_timeout
)
611 if (FAILED(hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &state
, NULL
)))
613 if (state
== expected
)
616 total_time
+= wait_step
;
618 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get fullscreen state, hr %#x.\n", hr
);
619 todo_wine_if(todo
) ok_(__FILE__
, line
)(state
== expected
,
620 "Got unexpected state %#x, expected %#x.\n", state
, expected
);
623 /* VidPN exclusive ownership doesn't change immediately.
624 * This helper is used to wait for the expected status */
625 #define get_expected_vidpn_exclusive_ownership(a, b) \
626 get_expected_vidpn_exclusive_ownership_(__LINE__, a, b)
627 static NTSTATUS
get_expected_vidpn_exclusive_ownership_(unsigned int line
,
628 const D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP
*desc
, NTSTATUS expected
)
630 static const unsigned int wait_timeout
= 2000;
631 static const unsigned int wait_step
= 100;
632 unsigned int total_time
= 0;
635 while (total_time
< wait_timeout
)
637 status
= pD3DKMTCheckVidPnExclusiveOwnership(desc
);
638 if (status
== expected
)
641 total_time
+= wait_step
;
646 static HWND
create_window(void)
648 RECT r
= {0, 0, 640, 480};
650 AdjustWindowRect(&r
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, FALSE
);
652 return CreateWindowA("static", "dxgi_test", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
653 0, 0, r
.right
- r
.left
, r
.bottom
- r
.top
, NULL
, NULL
, NULL
, NULL
);
656 static IDXGIAdapter
*create_adapter(void)
658 IDXGIFactory4
*factory4
;
659 IDXGIFactory
*factory
;
660 IDXGIAdapter
*adapter
;
663 if (!use_warp_adapter
&& !use_adapter_idx
)
666 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
)))
668 trace("Failed to create IDXGIFactory, hr %#x.\n", hr
);
673 if (use_warp_adapter
)
675 if (SUCCEEDED(hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory4
, (void **)&factory4
)))
677 hr
= IDXGIFactory4_EnumWarpAdapter(factory4
, &IID_IDXGIAdapter
, (void **)&adapter
);
678 IDXGIFactory4_Release(factory4
);
682 trace("Failed to get IDXGIFactory4, hr %#x.\n", hr
);
687 hr
= IDXGIFactory_EnumAdapters(factory
, use_adapter_idx
, &adapter
);
689 IDXGIFactory_Release(factory
);
691 trace("Failed to get adapter, hr %#x.\n", hr
);
695 static IDXGIDevice
*create_device(unsigned int flags
)
697 IDXGIDevice
*dxgi_device
;
698 ID3D10Device1
*device
;
699 IDXGIAdapter
*adapter
;
702 adapter
= create_adapter();
703 hr
= D3D10CreateDevice1(adapter
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
704 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
);
706 IDXGIAdapter_Release(adapter
);
710 if (SUCCEEDED(D3D10CreateDevice1(NULL
, D3D10_DRIVER_TYPE_WARP
, NULL
,
711 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
)))
713 if (SUCCEEDED(D3D10CreateDevice1(NULL
, D3D10_DRIVER_TYPE_REFERENCE
, NULL
,
714 flags
, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
)))
720 hr
= ID3D10Device1_QueryInterface(device
, &IID_IDXGIDevice
, (void **)&dxgi_device
);
721 ok(SUCCEEDED(hr
), "Created device does not implement IDXGIDevice\n");
722 ID3D10Device1_Release(device
);
727 static IDXGIDevice
*create_d3d11_device(void)
729 static const D3D_FEATURE_LEVEL feature_level
[] =
731 D3D_FEATURE_LEVEL_11_0
,
733 unsigned int feature_level_count
= ARRAY_SIZE(feature_level
);
734 IDXGIDevice
*device
= NULL
;
735 ID3D11Device
*d3d_device
;
738 if (!pD3D11CreateDevice
)
741 hr
= pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_HARDWARE
, NULL
, 0, feature_level
, feature_level_count
,
742 D3D11_SDK_VERSION
, &d3d_device
, NULL
, NULL
);
744 hr
= pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_WARP
, NULL
, 0, feature_level
, feature_level_count
,
745 D3D11_SDK_VERSION
, &d3d_device
, NULL
, NULL
);
747 hr
= pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_REFERENCE
, NULL
, 0, feature_level
, feature_level_count
,
748 D3D11_SDK_VERSION
, &d3d_device
, NULL
, NULL
);
752 hr
= ID3D11Device_QueryInterface(d3d_device
, &IID_IDXGIDevice
, (void **)&device
);
753 ok(SUCCEEDED(hr
), "Created device does not implement IDXGIDevice.\n");
754 ID3D11Device_Release(d3d_device
);
760 static ID3D12Device
*create_d3d12_device(void)
762 IDXGIAdapter
*adapter
;
763 ID3D12Device
*device
;
766 if (!pD3D12CreateDevice
)
769 adapter
= create_adapter();
770 hr
= pD3D12CreateDevice((IUnknown
*)adapter
, D3D_FEATURE_LEVEL_11_0
, &IID_ID3D12Device
, (void **)&device
);
772 IDXGIAdapter_Release(adapter
);
779 static ID3D12CommandQueue
*create_d3d12_direct_queue(ID3D12Device
*device
)
781 D3D12_COMMAND_QUEUE_DESC command_queue_desc
;
782 ID3D12CommandQueue
*queue
;
785 command_queue_desc
.Type
= D3D12_COMMAND_LIST_TYPE_DIRECT
;
786 command_queue_desc
.Priority
= D3D12_COMMAND_QUEUE_PRIORITY_NORMAL
;
787 command_queue_desc
.Flags
= D3D12_COMMAND_QUEUE_FLAG_NONE
;
788 command_queue_desc
.NodeMask
= 0;
789 hr
= ID3D12Device_CreateCommandQueue(device
, &command_queue_desc
,
790 &IID_ID3D12CommandQueue
, (void **)&queue
);
791 ok(hr
== S_OK
, "Failed to create command queue, hr %#x.\n", hr
);
795 static HRESULT
wait_for_fence(ID3D12Fence
*fence
, UINT64 value
)
801 if (ID3D12Fence_GetCompletedValue(fence
) >= value
)
804 if (!(event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
)))
807 if (FAILED(hr
= ID3D12Fence_SetEventOnCompletion(fence
, value
, event
)))
813 ret
= WaitForSingleObject(event
, INFINITE
);
815 return ret
== WAIT_OBJECT_0
? S_OK
: E_FAIL
;
818 #define wait_queue_idle(a, b) wait_queue_idle_(__LINE__, a, b)
819 static void wait_queue_idle_(unsigned int line
, ID3D12Device
*device
, ID3D12CommandQueue
*queue
)
824 hr
= ID3D12Device_CreateFence(device
, 0, D3D12_FENCE_FLAG_NONE
,
825 &IID_ID3D12Fence
, (void **)&fence
);
826 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to create fence, hr %#x.\n", hr
);
828 hr
= ID3D12CommandQueue_Signal(queue
, fence
, 1);
829 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to signal fence, hr %#x.\n", hr
);
830 hr
= wait_for_fence(fence
, 1);
831 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to wait for fence, hr %#x.\n", hr
);
833 ID3D12Fence_Release(fence
);
836 #define wait_device_idle(a) wait_device_idle_(__LINE__, a)
837 static void wait_device_idle_(unsigned int line
, IUnknown
*device
)
839 ID3D12Device
*d3d12_device
;
840 ID3D12CommandQueue
*queue
;
843 hr
= IUnknown_QueryInterface(device
, &IID_ID3D12CommandQueue
, (void **)&queue
);
847 hr
= ID3D12CommandQueue_GetDevice(queue
, &IID_ID3D12Device
, (void **)&d3d12_device
);
848 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get d3d12 device, hr %#x.\n", hr
);
850 wait_queue_idle_(line
, d3d12_device
, queue
);
852 ID3D12CommandQueue_Release(queue
);
853 ID3D12Device_Release(d3d12_device
);
856 #define get_factory(a, b, c) get_factory_(__LINE__, a, b, c)
857 static void get_factory_(unsigned int line
, IUnknown
*device
, BOOL is_d3d12
, IDXGIFactory
**factory
)
859 IDXGIDevice
*dxgi_device
;
860 IDXGIAdapter
*adapter
;
865 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)factory
);
866 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to create factory, hr %#x.\n", hr
);
870 dxgi_device
= (IDXGIDevice
*)device
;
871 hr
= IDXGIDevice_GetAdapter(dxgi_device
, &adapter
);
872 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
873 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)factory
);
874 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
875 IDXGIAdapter_Release(adapter
);
879 #define get_adapter(a, b) get_adapter_(__LINE__, a, b)
880 static IDXGIAdapter
*get_adapter_(unsigned int line
, IUnknown
*device
, BOOL is_d3d12
)
882 IDXGIAdapter
*adapter
= NULL
;
883 ID3D12Device
*d3d12_device
;
884 IDXGIFactory4
*factory4
;
885 IDXGIFactory
*factory
;
891 get_factory_(line
, device
, is_d3d12
, &factory
);
892 hr
= ID3D12CommandQueue_GetDevice((ID3D12CommandQueue
*)device
, &IID_ID3D12Device
, (void **)&d3d12_device
);
893 ok_(__FILE__
, line
)(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
894 luid
= ID3D12Device_GetAdapterLuid(d3d12_device
);
895 ID3D12Device_Release(d3d12_device
);
896 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory4
, (void **)&factory4
);
897 ok_(__FILE__
, line
)(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
898 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, luid
, &IID_IDXGIAdapter
, (void **)&adapter
);
899 IDXGIFactory4_Release(factory4
);
900 IDXGIFactory_Release(factory
);
904 hr
= IDXGIDevice_GetAdapter((IDXGIDevice
*)device
, &adapter
);
905 ok_(__FILE__
, line
)(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
911 static void test_adapter_desc(void)
913 DXGI_ADAPTER_DESC1 desc1
;
914 IDXGIAdapter1
*adapter1
;
915 DXGI_ADAPTER_DESC desc
;
916 IDXGIAdapter
*adapter
;
921 if (!(device
= create_device(0)))
923 skip("Failed to create device.\n");
927 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
928 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
930 hr
= IDXGIAdapter_GetDesc(adapter
, NULL
);
931 ok(hr
== E_INVALIDARG
, "GetDesc returned %#x, expected %#x.\n",
934 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
935 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
937 trace("%s.\n", wine_dbgstr_w(desc
.Description
));
938 trace("%04x: %04x:%04x (rev %02x).\n",
939 desc
.SubSysId
, desc
.VendorId
, desc
.DeviceId
, desc
.Revision
);
940 trace("Dedicated video memory: %lu (%lu MB).\n",
941 desc
.DedicatedVideoMemory
, desc
.DedicatedVideoMemory
/ (1024 * 1024));
942 trace("Dedicated system memory: %lu (%lu MB).\n",
943 desc
.DedicatedSystemMemory
, desc
.DedicatedSystemMemory
/ (1024 * 1024));
944 trace("Shared system memory: %lu (%lu MB).\n",
945 desc
.SharedSystemMemory
, desc
.SharedSystemMemory
/ (1024 * 1024));
946 trace("LUID: %08x:%08x.\n", desc
.AdapterLuid
.HighPart
, desc
.AdapterLuid
.LowPart
);
948 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
949 ok(SUCCEEDED(hr
) || broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#x.\n", hr
);
950 if (hr
== E_NOINTERFACE
)
953 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &desc1
);
954 ok(SUCCEEDED(hr
), "GetDesc1 failed, hr %#x.\n", hr
);
956 ok(!lstrcmpW(desc
.Description
, desc1
.Description
),
957 "Got unexpected description %s.\n", wine_dbgstr_w(desc1
.Description
));
958 ok(desc1
.VendorId
== desc
.VendorId
, "Got unexpected vendor ID %04x.\n", desc1
.VendorId
);
959 ok(desc1
.DeviceId
== desc
.DeviceId
, "Got unexpected device ID %04x.\n", desc1
.DeviceId
);
960 ok(desc1
.SubSysId
== desc
.SubSysId
, "Got unexpected sub system ID %04x.\n", desc1
.SubSysId
);
961 ok(desc1
.Revision
== desc
.Revision
, "Got unexpected revision %02x.\n", desc1
.Revision
);
962 ok(desc1
.DedicatedVideoMemory
== desc
.DedicatedVideoMemory
,
963 "Got unexpected dedicated video memory %lu.\n", desc1
.DedicatedVideoMemory
);
964 ok(desc1
.DedicatedSystemMemory
== desc
.DedicatedSystemMemory
,
965 "Got unexpected dedicated system memory %lu.\n", desc1
.DedicatedSystemMemory
);
966 ok(desc1
.SharedSystemMemory
== desc
.SharedSystemMemory
,
967 "Got unexpected shared system memory %lu.\n", desc1
.SharedSystemMemory
);
968 ok(equal_luid(desc1
.AdapterLuid
, desc
.AdapterLuid
),
969 "Got unexpected adapter LUID %08x:%08x.\n", desc1
.AdapterLuid
.HighPart
, desc1
.AdapterLuid
.LowPart
);
970 trace("Flags: %08x.\n", desc1
.Flags
);
972 IDXGIAdapter1_Release(adapter1
);
975 IDXGIAdapter_Release(adapter
);
976 refcount
= IDXGIDevice_Release(device
);
977 ok(!refcount
, "Device has %u references left.\n", refcount
);
980 static void test_adapter_luid(void)
982 DXGI_ADAPTER_DESC device_adapter_desc
, desc
, desc2
;
983 static const LUID luid
= {0xdeadbeef, 0xdeadbeef};
984 IDXGIAdapter
*adapter
, *adapter2
;
985 unsigned int found_adapter_count
;
986 unsigned int adapter_index
;
987 BOOL is_null_luid_adapter
;
988 IDXGIFactory4
*factory4
;
989 IDXGIFactory
*factory
;
990 BOOL have_unique_luid
;
995 if (!(device
= create_device(0)))
997 skip("Failed to create device.\n");
1001 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1002 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1003 hr
= IDXGIAdapter_GetDesc(adapter
, &device_adapter_desc
);
1004 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1005 IDXGIAdapter_Release(adapter
);
1006 refcount
= IDXGIDevice_Release(device
);
1007 ok(!refcount
, "Device has %u references left.\n", refcount
);
1009 is_null_luid_adapter
= !device_adapter_desc
.AdapterLuid
.LowPart
1010 && !device_adapter_desc
.SubSysId
&& !device_adapter_desc
.Revision
1011 && !device_adapter_desc
.VendorId
&& !device_adapter_desc
.DeviceId
;
1013 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
1014 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
1016 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory4
, (void **)&factory4
);
1017 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
1019 have_unique_luid
= TRUE
;
1020 found_adapter_count
= 0;
1022 while ((hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)) == S_OK
)
1024 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1025 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1027 if (equal_luid(desc
.AdapterLuid
, device_adapter_desc
.AdapterLuid
))
1029 check_adapter_desc(&desc
, &device_adapter_desc
);
1030 ++found_adapter_count
;
1033 if (equal_luid(desc
.AdapterLuid
, luid
))
1034 have_unique_luid
= FALSE
;
1038 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, desc
.AdapterLuid
,
1039 &IID_IDXGIAdapter
, (void **)&adapter2
);
1040 ok(hr
== S_OK
, "Failed to enum adapter by LUID, hr %#x.\n", hr
);
1041 hr
= IDXGIAdapter_GetDesc(adapter2
, &desc2
);
1042 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1043 check_adapter_desc(&desc2
, &desc
);
1044 ok(adapter2
!= adapter
, "Expected to get new instance of IDXGIAdapter.\n");
1045 refcount
= IDXGIAdapter_Release(adapter2
);
1046 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1049 refcount
= IDXGIAdapter_Release(adapter
);
1050 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1054 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
1056 /* Older versions of WARP aren't enumerated by IDXGIFactory_EnumAdapters(). */
1057 ok(found_adapter_count
== 1 || broken(is_null_luid_adapter
),
1058 "Found %u adapters for LUID %08x:%08x.\n",
1059 found_adapter_count
, device_adapter_desc
.AdapterLuid
.HighPart
,
1060 device_adapter_desc
.AdapterLuid
.LowPart
);
1063 IDXGIFactory4_Release(factory4
);
1064 refcount
= IDXGIFactory_Release(factory
);
1065 ok(!refcount
, "Factory has %u references left.\n", refcount
);
1067 if (!pCreateDXGIFactory2
1068 || FAILED(hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory4
, (void **)&factory4
)))
1070 skip("DXGI 1.4 is not available.\n");
1074 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1075 &IID_IDXGIAdapter
, NULL
);
1076 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1078 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1079 &IID_IDXGIAdapter
, (void **)&adapter
);
1080 ok(hr
== S_OK
, "Failed to enum adapter by LUID, hr %#x.\n", hr
);
1083 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1084 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1085 check_adapter_desc(&desc
, &device_adapter_desc
);
1086 refcount
= IDXGIAdapter_Release(adapter
);
1087 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1090 if (have_unique_luid
)
1092 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, luid
, &IID_IDXGIAdapter
, (void **)&adapter
);
1093 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
1097 skip("Our LUID is not unique.\n");
1100 refcount
= IDXGIFactory4_Release(factory4
);
1101 ok(!refcount
, "Factory has %u references left.\n", refcount
);
1104 static void test_query_video_memory_info(void)
1106 DXGI_QUERY_VIDEO_MEMORY_INFO memory_info
;
1107 IDXGIAdapter3
*adapter3
;
1108 IDXGIAdapter
*adapter
;
1109 IDXGIDevice
*device
;
1113 if (!(device
= create_device(0)))
1115 skip("Failed to create device.\n");
1119 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1120 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1121 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter3
, (void **)&adapter3
);
1122 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
1123 if (hr
== E_NOINTERFACE
)
1126 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL
, &memory_info
);
1127 ok(hr
== S_OK
, "Failed to query video memory info, hr %#x.\n", hr
);
1128 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1129 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1130 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1131 wine_dbgstr_longlong(memory_info
.Budget
));
1132 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1133 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1135 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
, &memory_info
);
1136 ok(hr
== S_OK
, "Failed to query video memory info, hr %#x.\n", hr
);
1137 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1138 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1139 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1140 wine_dbgstr_longlong(memory_info
.Budget
));
1141 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1142 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1144 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
+ 1, &memory_info
);
1145 ok(hr
== E_INVALIDARG
, "Failed to query video memory info, hr %#x.\n", hr
);
1147 IDXGIAdapter3_Release(adapter3
);
1150 IDXGIAdapter_Release(adapter
);
1151 refcount
= IDXGIDevice_Release(device
);
1152 ok(!refcount
, "Device has %u references left.\n", refcount
);
1155 static void test_check_interface_support(void)
1157 LARGE_INTEGER driver_version
;
1158 IDXGIAdapter
*adapter
;
1159 IDXGIDevice
*device
;
1164 if (!(device
= create_device(0)))
1166 skip("Failed to create device.\n");
1170 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1171 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1173 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, NULL
);
1174 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1175 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, &driver_version
);
1176 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1177 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, NULL
);
1178 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1179 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, &driver_version
);
1180 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1182 trace("UMD version: %u.%u.%u.%u.\n",
1183 HIWORD(U(driver_version
).HighPart
), LOWORD(U(driver_version
).HighPart
),
1184 HIWORD(U(driver_version
).LowPart
), LOWORD(U(driver_version
).LowPart
));
1186 hr
= IDXGIDevice_QueryInterface(device
, &IID_ID3D10Device1
, (void **)&iface
);
1189 IUnknown_Release(iface
);
1190 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, NULL
);
1191 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1192 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, &driver_version
);
1193 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1197 win_skip("D3D10.1 is not supported.\n");
1200 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, NULL
);
1201 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#x.\n", hr
);
1202 driver_version
.LowPart
= driver_version
.HighPart
= 0xdeadbeef;
1203 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, &driver_version
);
1204 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#x.\n", hr
);
1205 ok(driver_version
.HighPart
== 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version
.HighPart
);
1206 ok(driver_version
.LowPart
== 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version
.LowPart
);
1208 IDXGIAdapter_Release(adapter
);
1209 refcount
= IDXGIDevice_Release(device
);
1210 ok(!refcount
, "Device has %u references left.\n", refcount
);
1213 static void test_create_surface(void)
1215 ID3D11Texture2D
*texture2d
;
1216 DXGI_SURFACE_DESC desc
;
1217 IDXGISurface
*surface
;
1218 IDXGIDevice
*device
;
1222 if (!(device
= create_device(0)))
1224 skip("Failed to create device.\n");
1230 desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1231 desc
.SampleDesc
.Count
= 1;
1232 desc
.SampleDesc
.Quality
= 0;
1234 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1235 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1237 check_interface(surface
, &IID_ID3D10Texture2D
, TRUE
, FALSE
);
1238 /* Not available on all Windows versions. */
1239 check_interface(surface
, &IID_ID3D11Texture2D
, TRUE
, TRUE
);
1240 /* Not available on all Windows versions. */
1241 check_interface(surface
, &IID_IDXGISurface1
, TRUE
, TRUE
);
1243 IDXGISurface_Release(surface
);
1244 refcount
= IDXGIDevice_Release(device
);
1245 ok(!refcount
, "Device has %u references left.\n", refcount
);
1247 /* DXGI_USAGE_UNORDERED_ACCESS */
1248 if (!(device
= create_d3d11_device()))
1250 skip("Failed to create D3D11 device.\n");
1255 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_UNORDERED_ACCESS
, NULL
, &surface
);
1256 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1260 ID3D11UnorderedAccessView
*uav
;
1261 ID3D11Device
*d3d_device
;
1263 hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture2d
);
1264 ok(SUCCEEDED(hr
), "Failed to get texture interface, hr %#x.\n", hr
);
1266 ID3D11Texture2D_GetDevice(texture2d
, &d3d_device
);
1268 hr
= ID3D11Device_CreateUnorderedAccessView(d3d_device
, (ID3D11Resource
*)texture2d
, NULL
, &uav
);
1269 ok(SUCCEEDED(hr
), "Failed to create unordered access view, hr %#x.\n", hr
);
1270 ID3D11UnorderedAccessView_Release(uav
);
1272 ID3D11Device_Release(d3d_device
);
1273 ID3D11Texture2D_Release(texture2d
);
1275 IDXGISurface_Release(surface
);
1278 refcount
= IDXGIDevice_Release(device
);
1279 ok(!refcount
, "Device has %u references left.\n", refcount
);
1282 static void test_parents(void)
1284 DXGI_SURFACE_DESC surface_desc
;
1285 IDXGISurface
*surface
;
1286 IDXGIFactory
*factory
;
1287 IDXGIAdapter
*adapter
;
1288 IDXGIDevice
*device
;
1289 IDXGIOutput
*output
;
1294 if (!(device
= create_device(0)))
1296 skip("Failed to create device.\n");
1300 surface_desc
.Width
= 512;
1301 surface_desc
.Height
= 512;
1302 surface_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1303 surface_desc
.SampleDesc
.Count
= 1;
1304 surface_desc
.SampleDesc
.Quality
= 0;
1306 hr
= IDXGIDevice_CreateSurface(device
, &surface_desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1307 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1309 hr
= IDXGISurface_GetParent(surface
, &IID_IDXGIDevice
, (void **)&parent
);
1310 IDXGISurface_Release(surface
);
1311 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1312 ok(parent
== (IUnknown
*)device
, "Got parent %p, expected %p.\n", parent
, device
);
1313 IUnknown_Release(parent
);
1315 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1316 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1318 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1319 if (hr
== DXGI_ERROR_NOT_FOUND
)
1321 skip("Adapter has not outputs.\n");
1325 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1327 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&parent
);
1328 IDXGIOutput_Release(output
);
1329 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1330 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1331 IUnknown_Release(parent
);
1334 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1335 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1337 hr
= IDXGIFactory_GetParent(factory
, &IID_IUnknown
, (void **)&parent
);
1338 ok(hr
== E_NOINTERFACE
, "GetParent returned %#x, expected %#x.\n", hr
, E_NOINTERFACE
);
1339 ok(parent
== NULL
, "Got parent %p, expected %p.\n", parent
, NULL
);
1340 IDXGIFactory_Release(factory
);
1342 hr
= IDXGIDevice_GetParent(device
, &IID_IDXGIAdapter
, (void **)&parent
);
1343 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1344 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1345 IUnknown_Release(parent
);
1347 IDXGIAdapter_Release(adapter
);
1348 refcount
= IDXGIDevice_Release(device
);
1349 ok(!refcount
, "Device has %u references left.\n", refcount
);
1352 static void test_output(void)
1354 unsigned int mode_count
, mode_count_comp
, i
, last_height
, last_width
;
1355 double last_refresh_rate
;
1356 IDXGIAdapter
*adapter
;
1357 IDXGIDevice
*device
;
1359 IDXGIOutput
*output
;
1361 DXGI_MODE_DESC
*modes
;
1363 if (!(device
= create_device(0)))
1365 skip("Failed to create device.\n");
1369 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1370 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1372 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, NULL
);
1373 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1375 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1376 if (hr
== DXGI_ERROR_NOT_FOUND
)
1378 skip("Adapter doesn't have any outputs.\n");
1379 IDXGIAdapter_Release(adapter
);
1380 IDXGIDevice_Release(device
);
1383 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1385 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, NULL
, NULL
);
1386 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1388 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1390 || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Remote Desktop Services / Win 7 testbot */
1391 "Failed to list modes, hr %#x.\n", hr
);
1392 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1394 win_skip("GetDisplayModeList() not supported.\n");
1395 IDXGIOutput_Release(output
);
1396 IDXGIAdapter_Release(adapter
);
1397 IDXGIDevice_Release(device
);
1400 mode_count_comp
= mode_count
;
1402 hr
= IDXGIOutput_GetDisplayModeList(output
, 0, 0, &mode_count
, NULL
);
1403 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1404 ok(!mode_count
, "Got unexpected mode_count %u.\n", mode_count
);
1406 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1407 DXGI_ENUM_MODES_SCALING
, &mode_count
, NULL
);
1408 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1409 ok(mode_count
>= mode_count_comp
, "Got unexpected mode_count %u, expected >= %u.\n", mode_count
, mode_count_comp
);
1410 mode_count_comp
= mode_count
;
1412 modes
= heap_calloc(mode_count
+ 10, sizeof(*modes
));
1413 ok(!!modes
, "Failed to allocate memory.\n");
1415 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1416 DXGI_ENUM_MODES_SCALING
, NULL
, modes
);
1417 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1418 ok(!modes
[0].Height
, "No output was expected.\n");
1421 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1422 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1423 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
1424 ok(!modes
[0].Height
, "No output was expected.\n");
1426 mode_count
= mode_count_comp
;
1427 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1428 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1429 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1430 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1432 last_width
= last_height
= 0;
1433 last_refresh_rate
= 0.;
1434 for (i
= 0; i
< mode_count
; i
++)
1436 double refresh_rate
= modes
[i
].RefreshRate
.Numerator
/ (double)modes
[i
].RefreshRate
.Denominator
;
1438 ok(modes
[i
].Width
&& modes
[i
].Height
, "Mode %u: Invalid dimensions %ux%u.\n",
1439 i
, modes
[i
].Width
, modes
[i
].Height
);
1441 ok(modes
[i
].Width
>= last_width
,
1442 "Mode %u: Modes should have been sorted, width %u < %u.\n", i
, modes
[i
].Width
, last_width
);
1443 if (modes
[i
].Width
!= last_width
)
1445 last_width
= modes
[i
].Width
;
1447 last_refresh_rate
= 0.;
1451 ok(modes
[i
].Height
>= last_height
,
1452 "Mode %u: Modes should have been sorted, height %u < %u.\n", i
, modes
[i
].Height
, last_height
);
1453 if (modes
[i
].Height
!= last_height
)
1455 last_height
= modes
[i
].Height
;
1456 last_refresh_rate
= 0.;
1460 ok(refresh_rate
>= last_refresh_rate
,
1461 "Mode %u: Modes should have been sorted, refresh rate %f < %f.\n", i
, refresh_rate
, last_refresh_rate
);
1462 if (refresh_rate
!= last_refresh_rate
)
1463 last_refresh_rate
= refresh_rate
;
1467 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1468 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1469 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1470 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1472 if (mode_count_comp
)
1474 mode_count
= mode_count_comp
- 1;
1475 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1476 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1477 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
1478 ok(mode_count
== mode_count_comp
- 1, "Got unexpected mode_count %u, expected %u.\n",
1479 mode_count
, mode_count_comp
- 1);
1483 skip("Not enough modes for test.\n");
1487 IDXGIOutput_Release(output
);
1488 IDXGIAdapter_Release(adapter
);
1489 refcount
= IDXGIDevice_Release(device
);
1490 ok(!refcount
, "Device has %u references left.\n", refcount
);
1493 static void test_find_closest_matching_mode(void)
1495 static const DXGI_MODE_SCALING scaling_tests
[] =
1497 DXGI_MODE_SCALING_CENTERED
,
1498 DXGI_MODE_SCALING_STRETCHED
1500 DXGI_MODE_DESC
*modes
, mode
, matching_mode
;
1501 unsigned int i
, j
, mode_count
;
1502 IDXGIAdapter
*adapter
;
1503 IDXGIDevice
*device
;
1504 IDXGIOutput
*output
;
1508 if (!(device
= create_device(0)))
1510 skip("Failed to create device.\n");
1514 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1515 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1517 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1518 if (hr
== DXGI_ERROR_NOT_FOUND
)
1520 win_skip("Adapter doesn't have any outputs.\n");
1521 IDXGIAdapter_Release(adapter
);
1522 IDXGIDevice_Release(device
);
1525 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1527 memset(&mode
, 0, sizeof(mode
));
1528 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1529 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
1530 "Got unexpected hr %#x.\n", hr
);
1531 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1533 win_skip("FindClosestMatchingMode() not supported.\n");
1537 memset(&mode
, 0, sizeof(mode
));
1538 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, (IUnknown
*)device
);
1539 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1541 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1542 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1544 modes
= heap_calloc(mode_count
, sizeof(*modes
));
1545 ok(!!modes
, "Failed to allocate memory.\n");
1547 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
1548 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1550 for (i
= 0; i
< mode_count
; ++i
)
1553 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1554 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1555 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
);
1557 mode
.Format
= DXGI_FORMAT_UNKNOWN
;
1558 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1559 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1563 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1564 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1568 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1569 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1572 mode
.Width
= mode
.Height
= 0;
1573 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1574 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1575 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_RESOLUTION
);
1576 ok(matching_mode
.Width
> 0 && matching_mode
.Height
> 0, "Got unexpected resolution %ux%u.\n",
1577 matching_mode
.Width
, matching_mode
.Height
);
1580 mode
.RefreshRate
.Numerator
= mode
.RefreshRate
.Denominator
= 0;
1581 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1582 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1583 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_REFRESH_RATE
);
1584 ok(matching_mode
.RefreshRate
.Numerator
> 0 && matching_mode
.RefreshRate
.Denominator
> 0,
1585 "Got unexpected refresh rate %u / %u.\n",
1586 matching_mode
.RefreshRate
.Numerator
, matching_mode
.RefreshRate
.Denominator
);
1589 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1590 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1591 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1592 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1593 ok(matching_mode
.ScanlineOrdering
, "Got unexpected scanline ordering %#x.\n",
1594 matching_mode
.ScanlineOrdering
);
1596 memset(&mode
, 0, sizeof(mode
));
1597 mode
.Width
= modes
[i
].Width
;
1598 mode
.Height
= modes
[i
].Height
;
1599 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1600 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1601 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1602 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1604 memset(&mode
, 0, sizeof(mode
));
1605 mode
.Width
= modes
[i
].Width
- 1;
1606 mode
.Height
= modes
[i
].Height
- 1;
1607 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1608 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1609 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1610 check_mode_desc(&matching_mode
, &modes
[i
],
1611 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1613 memset(&mode
, 0, sizeof(mode
));
1614 mode
.Width
= modes
[i
].Width
+ 1;
1615 mode
.Height
= modes
[i
].Height
+ 1;
1616 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1617 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1618 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1619 check_mode_desc(&matching_mode
, &modes
[i
],
1620 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1623 memset(&mode
, 0, sizeof(mode
));
1624 mode
.Width
= mode
.Height
= 10;
1625 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1626 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1627 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1628 /* Find mode for the lowest resolution. */
1630 for (i
= 0; i
< mode_count
; ++i
)
1632 if (mode
.Width
>= modes
[i
].Width
&& mode
.Height
>= modes
[i
].Height
)
1635 check_mode_desc(&matching_mode
, &mode
, MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1637 memset(&mode
, 0, sizeof(mode
));
1638 mode
.Width
= modes
[0].Width
;
1639 mode
.Height
= modes
[0].Height
;
1640 mode
.Format
= modes
[0].Format
;
1641 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST
;
1642 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1643 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1644 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1646 memset(&mode
, 0, sizeof(mode
));
1647 mode
.Width
= modes
[0].Width
;
1648 mode
.Height
= modes
[0].Height
;
1649 mode
.Format
= modes
[0].Format
;
1650 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST
;
1651 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1652 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1653 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1655 for (i
= 0; i
< ARRAY_SIZE(scaling_tests
); ++i
)
1657 for (j
= 0; j
< mode_count
; ++j
)
1659 if (modes
[j
].Scaling
!= scaling_tests
[i
])
1662 memset(&mode
, 0, sizeof(mode
));
1663 mode
.Width
= modes
[j
].Width
;
1664 mode
.Height
= modes
[j
].Height
;
1665 mode
.Format
= modes
[j
].Format
;
1666 mode
.Scaling
= modes
[j
].Scaling
;
1667 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1668 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1669 check_mode_desc(&matching_mode
, &modes
[j
],
1670 MODE_DESC_IGNORE_REFRESH_RATE
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1678 IDXGIOutput_Release(output
);
1679 IDXGIAdapter_Release(adapter
);
1680 refcount
= IDXGIDevice_Release(device
);
1681 ok(!refcount
, "Device has %u references left.\n", refcount
);
1684 struct refresh_rates
1688 BOOL numerator_should_pass
;
1689 BOOL denominator_should_pass
;
1692 static void test_create_swapchain(void)
1694 struct swapchain_fullscreen_state initial_state
, expected_state
;
1695 unsigned int i
, expected_width
, expected_height
;
1696 DXGI_SWAP_CHAIN_DESC creation_desc
, result_desc
;
1697 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc
;
1698 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
1699 IDXGIDevice
*device
, *bgra_device
;
1700 ULONG refcount
, expected_refcount
;
1701 IUnknown
*obj
, *obj2
, *parent
;
1702 IDXGISwapChain1
*swapchain1
;
1703 RECT
*expected_client_rect
;
1704 IDXGISwapChain
*swapchain
;
1705 IDXGISurface1
*surface
;
1706 IDXGIAdapter
*adapter
;
1707 IDXGIFactory
*factory
;
1708 IDXGIOutput
*target
;
1713 const struct refresh_rates refresh_list
[] =
1715 {60, 60, FALSE
, FALSE
},
1716 {60, 0, TRUE
, FALSE
},
1717 {60, 1, TRUE
, TRUE
},
1718 { 0, 60, TRUE
, FALSE
},
1719 { 0, 0, TRUE
, FALSE
},
1722 if (!(device
= create_device(0)))
1724 skip("Failed to create device.\n");
1728 creation_desc
.BufferDesc
.Width
= 800;
1729 creation_desc
.BufferDesc
.Height
= 600;
1730 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
1731 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
1732 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1733 creation_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1734 creation_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
1735 creation_desc
.SampleDesc
.Count
= 1;
1736 creation_desc
.SampleDesc
.Quality
= 0;
1737 creation_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1738 creation_desc
.BufferCount
= 1;
1739 creation_desc
.OutputWindow
= NULL
;
1740 creation_desc
.Windowed
= TRUE
;
1741 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
1742 creation_desc
.Flags
= 0;
1744 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
1745 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1747 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1748 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1750 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1751 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
1753 expected_refcount
= get_refcount(adapter
);
1754 refcount
= get_refcount(factory
);
1755 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1756 refcount
= get_refcount(device
);
1757 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1759 creation_desc
.OutputWindow
= NULL
;
1760 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1761 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1763 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1764 memset(&initial_state
, 0, sizeof(initial_state
));
1765 capture_fullscreen_state(&initial_state
.fullscreen_state
, creation_desc
.OutputWindow
);
1767 hr
= IDXGIFactory_CreateSwapChain(factory
, NULL
, &creation_desc
, &swapchain
);
1768 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1769 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, NULL
, &swapchain
);
1770 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1771 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, NULL
);
1772 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1773 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1774 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1776 refcount
= get_refcount(adapter
);
1777 ok(refcount
>= expected_refcount
, "Got refcount %u, expected >= %u.\n", refcount
, expected_refcount
);
1778 refcount
= get_refcount(factory
);
1779 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1780 refcount
= get_refcount(device
);
1781 ok(refcount
== 3, "Got unexpected refcount %u.\n", refcount
);
1783 hr
= IDXGISwapChain_GetDesc(swapchain
, NULL
);
1784 ok(hr
== E_INVALIDARG
, "GetDesc unexpectedly returned %#x.\n", hr
);
1786 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IUnknown
, (void **)&parent
);
1787 ok(hr
== S_OK
, "Failed to get parent,%#x.\n", hr
);
1788 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1789 refcount
= IUnknown_Release(parent
);
1790 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1792 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IDXGIFactory
, (void **)&parent
);
1793 ok(hr
== S_OK
, "Failed to get parent,%#x.\n", hr
);
1794 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1795 refcount
= IUnknown_Release(parent
);
1796 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1798 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain1
, (void **)&swapchain1
);
1799 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
1800 "Failed to query IDXGISwapChain1 interface, hr %#x.\n", hr
);
1803 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, NULL
);
1804 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1805 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, &swapchain_desc
);
1806 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1807 ok(!swapchain_desc
.Stereo
, "Got unexpected stereo %#x.\n", swapchain_desc
.Stereo
);
1808 ok(swapchain_desc
.Scaling
== DXGI_SCALING_STRETCH
,
1809 "Got unexpected scaling %#x.\n", swapchain_desc
.Scaling
);
1810 ok(swapchain_desc
.AlphaMode
== DXGI_ALPHA_MODE_IGNORE
,
1811 "Got unexpected alpha mode %#x.\n", swapchain_desc
.AlphaMode
);
1812 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, NULL
);
1813 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1814 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, &fullscreen_desc
);
1815 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1816 ok(fullscreen_desc
.Windowed
== creation_desc
.Windowed
,
1817 "Got unexpected windowed %#x.\n", fullscreen_desc
.Windowed
);
1818 hr
= IDXGISwapChain1_GetHwnd(swapchain1
, &window
);
1819 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1820 ok(window
== creation_desc
.OutputWindow
, "Got unexpected window %p.\n", window
);
1821 IDXGISwapChain1_Release(swapchain1
);
1824 refcount
= IDXGISwapChain_Release(swapchain
);
1825 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
1827 refcount
= get_refcount(factory
);
1828 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1830 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1832 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1833 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1835 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1836 ok(hr
== S_OK
, "Test %u: Failed to create swapchain, hr %#x.\n", i
, hr
);
1838 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1839 ok(hr
== S_OK
, "Test %u: Failed to get swapchain desc, hr %#x.\n", i
, hr
);
1841 ok(result_desc
.Windowed
== creation_desc
.Windowed
, "Test %u: Got unexpected windowed %#x.\n",
1842 i
, result_desc
.Windowed
);
1844 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1845 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1846 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1848 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1849 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1850 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1852 fullscreen
= 0xdeadbeef;
1853 target
= (void *)0xdeadbeef;
1854 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1855 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
1856 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1857 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1859 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
1860 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1861 fullscreen
= 0xdeadbeef;
1862 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
1863 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1864 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1865 target
= (void *)0xdeadbeef;
1866 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
1867 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1868 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1870 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
1871 IDXGISwapChain_Release(swapchain
);
1874 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
1876 /* Test GDI-compatible swapchain */
1877 bgra_device
= create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT
);
1878 ok(!!bgra_device
, "Failed to create BGRA capable device.\n");
1880 hr
= IDXGIDevice_QueryInterface(bgra_device
, &IID_IUnknown
, (void **)&obj2
);
1881 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1883 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1884 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1886 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1891 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1892 ok(FAILED(hr
), "Expected GetDC() to fail, %#x\n", hr
);
1894 IDXGISurface1_Release(surface
);
1895 IDXGISwapChain_Release(swapchain
);
1897 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
1898 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE
;
1900 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1901 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1903 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1904 creation_desc
.Flags
= 0;
1906 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1907 ok(hr
== S_OK
, "Failed to get front buffer, hr %#x.\n", hr
);
1909 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1910 ok(hr
== S_OK
, "Expected GetDC() to succeed, %#x\n", hr
);
1911 IDXGISurface1_ReleaseDC(surface
, NULL
);
1913 IDXGISurface1_Release(surface
);
1914 IDXGISwapChain_Release(swapchain
);
1918 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1919 IDXGISwapChain_Release(swapchain
);
1921 IUnknown_Release(obj2
);
1922 IDXGIDevice_Release(bgra_device
);
1924 creation_desc
.Windowed
= FALSE
;
1926 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1928 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1929 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1931 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1932 ok(SUCCEEDED(hr
), "Test %u: Failed to create swapchain, hr %#x.\n", i
, hr
);
1934 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1935 ok(hr
== S_OK
, "Test %u: Failed to get swapchain desc, hr %#x.\n", i
, hr
);
1937 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1938 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1939 if (result_desc
.Windowed
!= creation_desc
.Windowed
)
1940 trace("Test %u: Failed to change fullscreen state.\n", i
);
1942 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1943 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1944 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1946 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1947 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1948 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1952 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1953 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
1954 ok(fullscreen
== !result_desc
.Windowed
, "Test %u: Got fullscreen %#x, expected %#x.\n",
1955 i
, fullscreen
, result_desc
.Windowed
);
1956 ok(result_desc
.Windowed
? !target
: !!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1957 if (!result_desc
.Windowed
)
1959 IDXGIOutput
*containing_output
;
1960 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
1961 ok(hr
== S_OK
, "Test %u: Failed to get containing output, hr %#x.\n", i
, hr
);
1962 ok(containing_output
== target
, "Test %u: Got unexpected containing output pointer %p.\n",
1963 i
, containing_output
);
1964 IDXGIOutput_Release(containing_output
);
1966 ok(output_belongs_to_adapter(target
, adapter
),
1967 "Test %u: Output %p doesn't belong to adapter %p.\n",
1968 i
, target
, adapter
);
1969 IDXGIOutput_Release(target
);
1971 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
1972 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1974 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
1975 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1976 ok(fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1978 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
1979 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1980 ok(!!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1981 IDXGIOutput_Release(target
);
1984 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
1985 ok(hr
== S_OK
, "Test %u: Failed to set fullscreen state, hr %#x.\n", i
, hr
);
1987 fullscreen
= 0xdeadbeef;
1988 target
= (void *)0xdeadbeef;
1989 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1990 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
1991 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1992 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1994 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
1995 IDXGISwapChain_Release(swapchain
);
1998 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2000 /* Test swapchain creation with DXGI_FORMAT_UNKNOWN. */
2001 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_UNKNOWN
;
2002 creation_desc
.Windowed
= TRUE
;
2003 creation_desc
.Flags
= 0;
2004 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2005 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
2007 creation_desc
.Windowed
= FALSE
;
2008 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2009 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
2011 creation_desc
.BufferCount
= 2;
2012 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
2013 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2014 ok(hr
== E_INVALIDARG
|| hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
2015 creation_desc
.BufferCount
= 1;
2016 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
2018 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2020 /* Test swapchain creation with backbuffer width and height equal to 0. */
2021 expected_state
= initial_state
;
2022 expected_client_rect
= &expected_state
.fullscreen_state
.client_rect
;
2025 expected_width
= expected_client_rect
->right
;
2026 expected_height
= expected_client_rect
->bottom
;
2028 creation_desc
.BufferDesc
.Width
= 0;
2029 creation_desc
.BufferDesc
.Height
= 0;
2030 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2031 creation_desc
.Windowed
= TRUE
;
2032 creation_desc
.Flags
= 0;
2033 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2034 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2035 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2036 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2037 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2038 result_desc
.BufferDesc
.Width
, expected_width
);
2039 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2040 result_desc
.BufferDesc
.Height
, expected_height
);
2041 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2042 IDXGISwapChain_Release(swapchain
);
2044 DestroyWindow(creation_desc
.OutputWindow
);
2045 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2046 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
2047 0, 0, 222, 222, 0, 0, 0, 0);
2048 expected_state
.fullscreen_state
.style
= WS_CLIPSIBLINGS
| WS_CAPTION
2049 | WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
2050 SetRect(&expected_state
.fullscreen_state
.window_rect
, 0, 0, 222, 222);
2051 GetClientRect(creation_desc
.OutputWindow
, expected_client_rect
);
2052 expected_width
= expected_client_rect
->right
;
2053 expected_height
= expected_client_rect
->bottom
;
2055 creation_desc
.BufferDesc
.Width
= 0;
2056 creation_desc
.BufferDesc
.Height
= 0;
2057 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2058 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2059 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2060 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2061 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2062 result_desc
.BufferDesc
.Width
, expected_width
);
2063 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2064 result_desc
.BufferDesc
.Height
, expected_height
);
2065 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2066 IDXGISwapChain_Release(swapchain
);
2068 DestroyWindow(creation_desc
.OutputWindow
);
2069 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2070 WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
2071 1, 1, 0, 0, 0, 0, 0, 0);
2072 expected_state
.fullscreen_state
.style
= WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
2073 expected_state
.fullscreen_state
.exstyle
= 0;
2074 SetRect(&expected_state
.fullscreen_state
.window_rect
, 1, 1, 1, 1);
2075 SetRectEmpty(expected_client_rect
);
2076 expected_width
= expected_height
= 8;
2078 creation_desc
.BufferDesc
.Width
= 0;
2079 creation_desc
.BufferDesc
.Height
= 0;
2080 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2081 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2082 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2083 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2084 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2085 result_desc
.BufferDesc
.Width
, expected_width
);
2086 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2087 result_desc
.BufferDesc
.Height
, expected_height
);
2088 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2089 IDXGISwapChain_Release(swapchain
);
2091 DestroyWindow(creation_desc
.OutputWindow
);
2092 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
2093 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2096 creation_desc
.Windowed
= FALSE
;
2097 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2098 ok(SUCCEEDED(hr
), "Failed to create swapchain, hr %#x.\n", hr
);
2099 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2100 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2101 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2102 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2103 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2104 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2105 "Failed to get containing output, hr %#x.\n", hr
);
2106 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2107 IDXGISwapChain_Release(swapchain
);
2108 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2110 win_skip("GetContainingOutput() not supported.\n");
2113 if (result_desc
.Windowed
)
2115 win_skip("Fullscreen not supported.\n");
2116 IDXGIOutput_Release(expected_state
.target
);
2120 creation_desc
.BufferDesc
.Width
= 0;
2121 creation_desc
.BufferDesc
.Height
= 0;
2122 creation_desc
.Windowed
= FALSE
;
2123 creation_desc
.Flags
= 0;
2124 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2125 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2126 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2127 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2129 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2130 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2131 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2132 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2133 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2134 result_desc
.BufferDesc
.Width
, expected_width
);
2135 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2136 result_desc
.BufferDesc
.Height
, expected_height
);
2137 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2138 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2139 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2140 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2141 IDXGISwapChain_Release(swapchain
);
2143 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
2144 creation_desc
.BufferDesc
.Width
= 0;
2145 creation_desc
.BufferDesc
.Height
= 0;
2146 creation_desc
.Windowed
= FALSE
;
2147 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2148 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2149 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2150 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2151 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2153 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2154 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2155 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2156 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2157 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2158 result_desc
.BufferDesc
.Width
, expected_width
);
2159 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2160 result_desc
.BufferDesc
.Height
, expected_height
);
2161 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2162 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2163 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2164 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2165 IDXGISwapChain_Release(swapchain
);
2167 IDXGIOutput_Release(expected_state
.target
);
2170 IUnknown_Release(obj
);
2171 refcount
= IDXGIDevice_Release(device
);
2172 ok(!refcount
, "Device has %u references left.\n", refcount
);
2173 refcount
= IDXGIAdapter_Release(adapter
);
2174 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
2175 refcount
= IDXGIFactory_Release(factory
);
2176 ok(!refcount
, "Factory has %u references left.\n", refcount
);
2177 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2178 DestroyWindow(creation_desc
.OutputWindow
);
2181 static HMONITOR
get_primary_if_right_side_secondary(const DXGI_OUTPUT_DESC
*output_desc
)
2183 HMONITOR primary
, secondary
;
2187 primary
= MonitorFromPoint(pt
, MONITOR_DEFAULTTONULL
);
2188 pt
.x
= output_desc
->DesktopCoordinates
.right
;
2189 secondary
= MonitorFromPoint(pt
, MONITOR_DEFAULTTONULL
);
2190 mi
.cbSize
= sizeof(mi
);
2191 if (secondary
&& secondary
!= primary
2192 && GetMonitorInfoW(primary
, &mi
) && (mi
.dwFlags
& MONITORINFOF_PRIMARY
))
2197 static void test_get_containing_output(IUnknown
*device
, BOOL is_d3d12
)
2199 unsigned int adapter_idx
, output_idx
, output_count
;
2200 DXGI_OUTPUT_DESC output_desc
, output_desc2
;
2201 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2202 IDXGIOutput
*output
, *output2
;
2203 MONITORINFOEXW monitor_info
;
2204 IDXGISwapChain
*swapchain
;
2205 IDXGIFactory
*factory
;
2206 IDXGIAdapter
*adapter
;
2207 POINT points
[4 * 16];
2216 adapter
= get_adapter(device
, is_d3d12
);
2219 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
2224 while ((hr
= IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
)) != DXGI_ERROR_NOT_FOUND
)
2226 ok(SUCCEEDED(hr
), "Failed to enumerate output %u, hr %#x.\n", output_count
, hr
);
2227 IDXGIOutput_Release(output
);
2230 IDXGIAdapter_Release(adapter
);
2232 swapchain_desc
.BufferDesc
.Width
= 100;
2233 swapchain_desc
.BufferDesc
.Height
= 100;
2234 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2235 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2236 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2237 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2238 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2239 swapchain_desc
.SampleDesc
.Count
= 1;
2240 swapchain_desc
.SampleDesc
.Quality
= 0;
2241 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2242 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2243 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2244 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 0, 0, 100, 100, 0, 0, 0, 0);
2245 swapchain_desc
.Windowed
= TRUE
;
2246 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2247 swapchain_desc
.Flags
= 0;
2249 get_factory(device
, is_d3d12
, &factory
);
2250 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2251 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2253 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, 0);
2254 ok(!!monitor
, "MonitorFromWindow failed.\n");
2256 monitor_info
.cbSize
= sizeof(monitor_info
);
2257 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2258 ok(ret
, "Failed to get monitor info.\n");
2260 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2261 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2262 "GetContainingOutput failed, hr %#x.\n", hr
);
2263 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2265 win_skip("GetContainingOutput() not supported.\n");
2269 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2270 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2272 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2273 ok(SUCCEEDED(hr
), "GetContainingOutput failed, hr %#x.\n", hr
);
2274 ok(output
!= output2
, "Got unexpected output pointers %p, %p.\n", output
, output2
);
2275 check_output_equal(output
, output2
);
2277 refcount
= IDXGIOutput_Release(output
);
2278 ok(!refcount
, "IDXGIOutput has %u references left.\n", refcount
);
2279 refcount
= IDXGIOutput_Release(output2
);
2280 ok(!refcount
, "IDXGIOutput has %u references left.\n", refcount
);
2282 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2283 "Got unexpected device name %s, expected %s.\n",
2284 wine_dbgstr_w(output_desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
2285 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2286 "Got unexpected desktop coordinates %s, expected %s.\n",
2287 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2288 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2290 primary
= get_primary_if_right_side_secondary(&output_desc
);
2292 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2295 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2298 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2299 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2302 /* Move the OutputWindow to the current output. */
2303 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2304 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2305 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2307 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2310 win_skip("Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2311 adapter_idx
, output_idx
, hr
);
2312 IDXGIOutput_Release(output
);
2316 check_output_equal(output
, output2
);
2318 refcount
= IDXGIOutput_Release(output2
);
2319 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
2320 adapter_idx
, output_idx
, refcount
);
2322 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
2323 for (i
= 0; i
< 4; ++i
)
2325 static const POINT offsets
[] =
2328 {-49, 0}, {-50, 0}, {-51, 0},
2329 { 0, -49}, { 0, -50}, { 0, -51},
2330 {-49, -49}, {-50, -49}, {-51, -49},
2331 {-49, -50}, {-50, -50}, {-51, -50},
2332 {-49, -51}, {-50, -51}, {-51, -51},
2334 unsigned int x
= 0, y
= 0;
2339 x
= output_desc
.DesktopCoordinates
.left
;
2340 y
= output_desc
.DesktopCoordinates
.top
;
2343 x
= output_desc
.DesktopCoordinates
.right
;
2344 y
= output_desc
.DesktopCoordinates
.top
;
2347 x
= output_desc
.DesktopCoordinates
.right
;
2348 y
= output_desc
.DesktopCoordinates
.bottom
;
2351 x
= output_desc
.DesktopCoordinates
.left
;
2352 y
= output_desc
.DesktopCoordinates
.bottom
;
2356 for (j
= 0; j
< ARRAY_SIZE(offsets
); ++j
)
2358 unsigned int idx
= ARRAY_SIZE(offsets
) * i
+ j
;
2359 assert(idx
< ARRAY_SIZE(points
));
2360 points
[idx
].x
= x
+ offsets
[j
].x
;
2361 points
[idx
].y
= y
+ offsets
[j
].y
;
2365 for (i
= 0; i
< ARRAY_SIZE(points
); ++i
)
2367 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, points
[i
].x
, points
[i
].y
,
2368 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2369 ok(ret
, "Adapter %u output %u point %u: Failed to set window position.\n",
2370 adapter_idx
, output_idx
, i
);
2372 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, MONITOR_DEFAULTTONEAREST
);
2373 ok(!!monitor
, "Adapter %u output %u point %u: Failed to get monitor from window.\n",
2374 adapter_idx
, output_idx
, i
);
2376 monitor_info
.cbSize
= sizeof(monitor_info
);
2377 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2378 ok(ret
, "Adapter %u output %u point %u: Failed to get monitor info.\n", adapter_idx
,
2381 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2382 /* Hack to prevent test failures with secondary on the right until multi-monitor support is improved. */
2383 todo_wine_if(primary
&& monitor
!= primary
)
2384 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
),
2385 "Adapter %u output %u point %u: Failed to get containing output, hr %#x.\n",
2386 adapter_idx
, output_idx
, i
, hr
);
2389 ok(!!output2
, "Adapter %u output %u point %u: Got unexpected containing output %p.\n",
2390 adapter_idx
, output_idx
, i
, output2
);
2391 hr
= IDXGIOutput_GetDesc(output2
, &output_desc
);
2392 ok(hr
== S_OK
, "Adapter %u output %u point %u: Failed to get output desc, hr %#x.\n",
2393 adapter_idx
, output_idx
, i
, hr
);
2394 refcount
= IDXGIOutput_Release(output2
);
2395 ok(!refcount
, "Adapter %u output %u point %u: IDXGIOutput has %u references left.\n",
2396 adapter_idx
, output_idx
, i
, refcount
);
2398 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2399 "Adapter %u output %u point %u: Got unexpected device name %s, expected %s.\n",
2400 adapter_idx
, output_idx
, i
, wine_dbgstr_w(output_desc
.DeviceName
),
2401 wine_dbgstr_w(monitor_info
.szDevice
));
2402 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2403 "Adapter %u output %u point %u: Expect desktop coordinates %s, got %s.\n",
2404 adapter_idx
, output_idx
, i
,
2405 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2406 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2408 IDXGIOutput_Release(output
);
2410 IDXGIAdapter_Release(adapter
);
2413 /* Test GetContainingOutput with a full screen swapchain. The containing output should stay
2414 * the same even if the device window is moved */
2415 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2418 skip("SetFullscreenState failed, hr %#x.\n", hr
);
2422 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2425 win_skip("GetContainingOutput failed, hr %#x.\n", hr
);
2426 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2430 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2433 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2436 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2437 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2439 IDXGIOutput_Release(output
);
2441 /* Move the OutputWindow to the current output. */
2442 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2443 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2444 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2446 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2447 ok(hr
== S_OK
, "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2448 adapter_idx
, output_idx
, hr
);
2449 ok(fullscreen
, "Adapter %u output %u: Expect swapchain full screen.\n", adapter_idx
,
2451 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2452 adapter_idx
, output_idx
, output2
, output
);
2453 IDXGIOutput_Release(output
);
2455 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2456 ok(hr
== S_OK
, "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2457 adapter_idx
, output_idx
, hr
);
2458 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2459 adapter_idx
, output_idx
, output2
, output
);
2460 IDXGIOutput_Release(output
);
2462 IDXGIAdapter_Release(adapter
);
2465 IDXGIOutput_Release(output2
);
2466 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2467 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
2469 /* Test GetContainingOutput after a full screen swapchain is made windowed by pressing
2470 * Alt+Enter, then move it to another output and use Alt+Enter to enter full screen */
2473 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2476 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
,
2477 output
? &output2
: &output
)); ++output_idx
)
2483 IDXGIAdapter_Release(adapter
);
2488 if (output
&& output2
)
2490 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2491 IDXGIOutput_Release(output
);
2494 skip("SetFullscreenState failed, hr %#x.\n", hr
);
2495 IDXGIOutput_Release(output2
);
2499 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to leave full screen on the first output */
2500 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2501 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2503 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2504 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
2505 ok(!fullscreen
, "Expect swapchain not full screen.\n");
2507 /* Move the swapchain output window to the second output */
2508 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2509 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2510 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc2
.DesktopCoordinates
.left
,
2511 output_desc2
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2512 ok(ret
, "SetWindowPos failed.\n");
2514 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to enter full screen on the second output */
2515 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2516 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2519 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2520 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
2521 ok(fullscreen
, "Expect swapchain full screen.\n");
2522 ok(!!output
, "Expect output not NULL.\n");
2523 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2524 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2525 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2526 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2527 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2528 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2529 wine_dbgstr_w(output_desc
.DeviceName
));
2530 IDXGIOutput_Release(output
);
2533 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2534 ok(hr
== S_OK
, "GetContainingOutput failed, hr %#x.\n", hr
);
2535 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2536 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2537 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2538 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2539 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2540 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2541 wine_dbgstr_w(output_desc
.DeviceName
));
2543 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2544 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
2548 skip("This test requires two outputs.\n");
2552 IDXGIOutput_Release(output
);
2554 IDXGIOutput_Release(output2
);
2557 refcount
= IDXGISwapChain_Release(swapchain
);
2558 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2559 refcount
= IDXGIFactory_Release(factory
);
2560 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
2561 DestroyWindow(swapchain_desc
.OutputWindow
);
2564 static void test_swapchain_fullscreen_state(IDXGISwapChain
*swapchain
,
2565 IDXGIAdapter
*adapter
, const struct swapchain_fullscreen_state
*initial_state
)
2567 MONITORINFOEXW monitor_info
, *output_monitor_info
;
2568 struct swapchain_fullscreen_state expected_state
;
2569 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2570 DXGI_OUTPUT_DESC output_desc
;
2571 unsigned int i
, output_count
;
2572 IDXGIOutput
*output
;
2576 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
2577 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2579 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2581 expected_state
= *initial_state
;
2582 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2583 &swapchain_desc
, &initial_state
->fullscreen_state
.monitor_rect
, 800, 600, NULL
);
2584 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2585 ok(SUCCEEDED(hr
), "GetContainingOutput failed, hr %#x.\n", hr
);
2587 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2588 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2591 skip("Could not change fullscreen state.\n");
2592 IDXGIOutput_Release(expected_state
.target
);
2595 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2597 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2598 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2599 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2601 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2602 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
2603 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2605 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2606 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2607 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2609 IDXGIOutput_Release(expected_state
.target
);
2610 expected_state
.target
= NULL
;
2613 while (IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
) != DXGI_ERROR_NOT_FOUND
)
2615 IDXGIOutput_Release(output
);
2619 output_monitor_info
= heap_calloc(output_count
, sizeof(*output_monitor_info
));
2620 ok(!!output_monitor_info
, "Failed to allocate memory.\n");
2621 for (i
= 0; i
< output_count
; ++i
)
2623 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2624 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2626 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2627 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2629 output_monitor_info
[i
].cbSize
= sizeof(*output_monitor_info
);
2630 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&output_monitor_info
[i
]);
2631 ok(ret
, "Failed to get monitor info.\n");
2633 IDXGIOutput_Release(output
);
2636 for (i
= 0; i
< output_count
; ++i
)
2638 RECT orig_monitor_rect
= output_monitor_info
[i
].rcMonitor
;
2639 IDXGIOutput
*target
;
2642 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2643 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2644 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2645 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2647 expected_state
= *initial_state
;
2648 expected_state
.target
= output
;
2649 expected_state
.fullscreen_state
.monitor
= output_desc
.Monitor
;
2650 expected_state
.fullscreen_state
.monitor_rect
= orig_monitor_rect
;
2651 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2652 &swapchain_desc
, &orig_monitor_rect
, 800, 600, NULL
);
2654 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2655 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2656 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2659 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2660 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2661 ok(target
== output
, "Got target pointer %p, expected %p.\n", target
, output
);
2662 IDXGIOutput_Release(target
);
2664 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2665 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2666 ok(fullscreen
, "Got unexpected fullscreen %#x.\n", hr
);
2668 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2669 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2670 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2671 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, output
);
2672 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
2673 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2674 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2675 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2676 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2679 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2680 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2681 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", hr
);
2683 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2684 monitor_info
.cbSize
= sizeof(monitor_info
);
2685 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2686 ok(ret
, "Failed to get monitor info.\n");
2687 ok(EqualRect(&monitor_info
.rcMonitor
, &orig_monitor_rect
), "Got monitor rect %s, expected %s.\n",
2688 wine_dbgstr_rect(&monitor_info
.rcMonitor
), wine_dbgstr_rect(&orig_monitor_rect
));
2690 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2691 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2693 IDXGIOutput_Release(output
);
2696 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2697 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2698 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2700 for (i
= 0; i
< output_count
; ++i
)
2702 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2703 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2705 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2706 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2708 monitor_info
.cbSize
= sizeof(monitor_info
);
2709 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2710 ok(ret
, "Failed to get monitor info.\n");
2712 ok(EqualRect(&monitor_info
.rcMonitor
, &output_monitor_info
[i
].rcMonitor
),
2713 "Got monitor rect %s, expected %s.\n",
2714 wine_dbgstr_rect(&monitor_info
.rcMonitor
),
2715 wine_dbgstr_rect(&output_monitor_info
[i
].rcMonitor
));
2717 IDXGIOutput_Release(output
);
2720 heap_free(output_monitor_info
);
2723 static void test_set_fullscreen(IUnknown
*device
, BOOL is_d3d12
)
2725 struct swapchain_fullscreen_state initial_state
;
2726 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2727 IDXGIAdapter
*adapter
= NULL
;
2728 IDXGISwapChain
*swapchain
;
2729 IDXGIFactory
*factory
;
2730 IDXGIOutput
*output
;
2735 get_factory(device
, is_d3d12
, &factory
);
2737 swapchain_desc
.BufferDesc
.Width
= 800;
2738 swapchain_desc
.BufferDesc
.Height
= 600;
2739 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2740 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2741 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2742 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2743 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2744 swapchain_desc
.SampleDesc
.Count
= 1;
2745 swapchain_desc
.SampleDesc
.Quality
= 0;
2746 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2747 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2748 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2749 swapchain_desc
.Windowed
= TRUE
;
2750 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2751 swapchain_desc
.Flags
= 0;
2753 memset(&initial_state
, 0, sizeof(initial_state
));
2754 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
2755 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2756 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2757 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2758 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2759 "Failed to get containing output, hr %#x.\n", hr
);
2762 skip("Could not get output.\n");
2765 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&adapter
);
2766 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
2767 IDXGIOutput_Release(output
);
2769 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2770 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2771 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
2772 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2773 "SetFullscreenState failed, hr %#x.\n", hr
);
2776 skip("Could not change fullscreen state.\n");
2779 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2780 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2781 refcount
= IDXGISwapChain_Release(swapchain
);
2782 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2784 DestroyWindow(swapchain_desc
.OutputWindow
);
2785 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2786 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2787 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2788 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2789 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2790 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2791 refcount
= IDXGISwapChain_Release(swapchain
);
2792 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2794 DestroyWindow(swapchain_desc
.OutputWindow
);
2795 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2796 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2797 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2798 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2799 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2800 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2801 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2802 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2803 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2804 DestroyWindow(swapchain_desc
.OutputWindow
);
2805 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2806 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2807 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2808 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2809 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2810 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2811 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2812 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2813 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2814 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2815 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2816 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2817 refcount
= IDXGISwapChain_Release(swapchain
);
2818 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2820 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2821 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2822 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2823 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2824 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2825 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2826 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2827 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2828 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2829 DestroyWindow(swapchain_desc
.OutputWindow
);
2830 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2831 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2832 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2833 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2834 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2835 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2836 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2837 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2838 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2839 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2840 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2841 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2842 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2843 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2844 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2845 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2846 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2847 refcount
= IDXGISwapChain_Release(swapchain
);
2848 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2850 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2851 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2852 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2853 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2854 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2855 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2856 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2860 IDXGIAdapter_Release(adapter
);
2861 refcount
= IDXGISwapChain_Release(swapchain
);
2862 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2863 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2864 DestroyWindow(swapchain_desc
.OutputWindow
);
2866 refcount
= IDXGIFactory_Release(factory
);
2867 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
2870 static void test_default_fullscreen_target_output(IUnknown
*device
, BOOL is_d3d12
)
2872 IDXGIOutput
*output
, *containing_output
, *target
;
2873 unsigned int adapter_idx
, output_idx
;
2874 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2875 DXGI_OUTPUT_DESC output_desc
;
2876 unsigned int width
, height
;
2877 IDXGISwapChain
*swapchain
;
2878 IDXGIFactory
*factory
;
2879 IDXGIAdapter
*adapter
;
2880 BOOL fullscreen
, ret
;
2885 get_factory(device
, is_d3d12
, &factory
);
2887 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2888 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2889 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2890 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2891 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2892 swapchain_desc
.SampleDesc
.Count
= 1;
2893 swapchain_desc
.SampleDesc
.Quality
= 0;
2894 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2895 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2896 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2897 swapchain_desc
.Flags
= 0;
2899 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2902 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2905 /* Windowed swapchain */
2906 swapchain_desc
.BufferDesc
.Width
= 640;
2907 swapchain_desc
.BufferDesc
.Height
= 480;
2908 swapchain_desc
.OutputWindow
= create_window();
2909 swapchain_desc
.Windowed
= TRUE
;
2910 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
,
2912 ok(SUCCEEDED(hr
), "Adapter %u output %u: CreateSwapChain failed, hr %#x.\n",
2913 adapter_idx
, output_idx
, hr
);
2915 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
2916 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2917 adapter_idx
, output_idx
, hr
);
2918 ok(!fullscreen
, "Adapter %u output %u: Expected not fullscreen.\n", adapter_idx
,
2920 ok(!containing_output
, "Adapter %u output %u: Expected a null output.\n", adapter_idx
,
2923 /* Move the OutputWindow to the current output. */
2924 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2925 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2927 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0,
2928 output_desc
.DesktopCoordinates
.left
, output_desc
.DesktopCoordinates
.top
,
2929 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2930 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#x.\n", adapter_idx
,
2931 output_idx
, GetLastError());
2933 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2934 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2935 "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n", adapter_idx
,
2937 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2939 win_skip("Adapter %u output %u: GetContainingOutput() not supported.\n",
2940 adapter_idx
, output_idx
);
2941 IDXGISwapChain_Release(swapchain
);
2942 IDXGIOutput_Release(output
);
2943 DestroyWindow(swapchain_desc
.OutputWindow
);
2947 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2948 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
2949 "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n", adapter_idx
,
2951 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
2953 skip("Adapter %u output %u: Could not change fullscreen state.\n", adapter_idx
,
2955 IDXGIOutput_Release(containing_output
);
2956 IDXGISwapChain_Release(swapchain
);
2957 IDXGIOutput_Release(output
);
2958 DestroyWindow(swapchain_desc
.OutputWindow
);
2961 GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
2962 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
2963 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
2964 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2965 wine_dbgstr_rect(&window_rect
));
2968 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2969 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2970 adapter_idx
, output_idx
, hr
);
2971 ok(target
!= containing_output
,
2972 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
2973 output_idx
, target
, containing_output
);
2974 check_output_equal(target
, containing_output
);
2976 refcount
= IDXGIOutput_Release(containing_output
);
2977 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
2978 adapter_idx
, output_idx
, refcount
);
2980 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2981 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2982 adapter_idx
, output_idx
, hr
);
2983 ok(containing_output
== target
,
2984 "Adapter %u output %u: Got unexpected containing output %p, expected %p.\n",
2985 adapter_idx
, output_idx
, containing_output
, target
);
2986 refcount
= IDXGIOutput_Release(containing_output
);
2987 ok(refcount
>= 2, "Adapter %u output %u: Got unexpected refcount %u.\n", adapter_idx
,
2988 output_idx
, refcount
);
2989 refcount
= IDXGIOutput_Release(target
);
2990 ok(refcount
>= 1, "Adapter %u output %u: Got unexpected refcount %u.\n", adapter_idx
,
2991 output_idx
, refcount
);
2993 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2994 ok(SUCCEEDED(hr
), "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n",
2995 adapter_idx
, output_idx
, hr
);
2996 refcount
= IDXGISwapChain_Release(swapchain
);
2997 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
2998 adapter_idx
, output_idx
, refcount
);
2999 DestroyWindow(swapchain_desc
.OutputWindow
);
3001 /* Full screen swapchain */
3002 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
3003 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
3004 swapchain_desc
.BufferDesc
.Width
= width
;
3005 swapchain_desc
.BufferDesc
.Height
= height
;
3006 swapchain_desc
.OutputWindow
= create_window();
3007 swapchain_desc
.Windowed
= FALSE
;
3008 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
3009 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
3010 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#x.\n", adapter_idx
,
3011 output_idx
, GetLastError());
3012 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
,
3016 skip("Adapter %u output %u: CreateSwapChain failed, hr %#x.\n", adapter_idx
,
3018 IDXGIOutput_Release(output
);
3019 DestroyWindow(swapchain_desc
.OutputWindow
);
3023 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
3024 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
3025 adapter_idx
, output_idx
, hr
);
3026 ok(fullscreen
, "Adapter %u output %u: Expected fullscreen.\n", adapter_idx
, output_idx
);
3027 ok(!!containing_output
, "Adapter %u output %u: Expected a valid output.\n", adapter_idx
,
3029 if (containing_output
)
3030 IDXGIOutput_Release(containing_output
);
3032 ret
= GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
3033 ok(ret
, "Adapter %u output %u: GetWindowRect failed, error %#x.\n", adapter_idx
,
3034 output_idx
, GetLastError());
3035 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
3036 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
3037 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3038 wine_dbgstr_rect(&window_rect
));
3040 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
3041 ok(hr
== S_OK
, "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
3042 adapter_idx
, output_idx
, hr
);
3043 ok(containing_output
!= output
,
3044 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
3045 output_idx
, output
, containing_output
);
3046 check_output_equal(output
, containing_output
);
3047 IDXGIOutput_Release(containing_output
);
3049 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3050 ok(hr
== S_OK
, "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n",
3051 adapter_idx
, output_idx
, hr
);
3052 refcount
= IDXGISwapChain_Release(swapchain
);
3053 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
3054 adapter_idx
, output_idx
, refcount
);
3055 refcount
= IDXGIOutput_Release(output
);
3056 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
3057 adapter_idx
, output_idx
, refcount
);
3058 DestroyWindow(swapchain_desc
.OutputWindow
);
3060 IDXGIAdapter_Release(adapter
);
3063 refcount
= IDXGIFactory_Release(factory
);
3064 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
3067 static void test_windowed_resize_target(IDXGISwapChain
*swapchain
, HWND window
,
3068 struct swapchain_fullscreen_state
*state
)
3070 struct swapchain_fullscreen_state expected_state
;
3071 struct fullscreen_state
*e
;
3072 DXGI_MODE_DESC mode
;
3080 unsigned int width
, height
;
3093 check_swapchain_fullscreen_state(swapchain
, state
);
3094 expected_state
= *state
;
3095 e
= &expected_state
.fullscreen_state
;
3097 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3099 SetRect(&e
->client_rect
, 0, 0, sizes
[i
].width
, sizes
[i
].height
);
3100 e
->window_rect
= e
->client_rect
;
3101 ret
= AdjustWindowRectEx(&e
->window_rect
, GetWindowLongW(window
, GWL_STYLE
),
3102 FALSE
, GetWindowLongW(window
, GWL_EXSTYLE
));
3103 ok(ret
, "AdjustWindowRectEx failed.\n");
3104 if (GetMenu(window
))
3105 e
->client_rect
.bottom
-= GetSystemMetrics(SM_CYMENU
);
3106 SetRect(&e
->window_rect
, 0, 0,
3107 e
->window_rect
.right
- e
->window_rect
.left
,
3108 e
->window_rect
.bottom
- e
->window_rect
.top
);
3109 GetWindowRect(window
, &window_rect
);
3110 OffsetRect(&e
->window_rect
, window_rect
.left
, window_rect
.top
);
3111 if (e
->window_rect
.right
>= e
->monitor_rect
.right
3112 || e
->window_rect
.bottom
>= e
->monitor_rect
.bottom
)
3114 skip("Test %u: Window %s does not fit on screen %s.\n",
3115 i
, wine_dbgstr_rect(&e
->window_rect
), wine_dbgstr_rect(&e
->monitor_rect
));
3119 memset(&mode
, 0, sizeof(mode
));
3120 mode
.Width
= sizes
[i
].width
;
3121 mode
.Height
= sizes
[i
].height
;
3122 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3123 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3124 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3127 ret
= SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOZORDER
);
3128 ok(ret
, "SetWindowPos failed, error %#x.\n", GetLastError());
3129 GetWindowRect(window
, &e
->window_rect
);
3130 GetClientRect(window
, &e
->client_rect
);
3131 ret
= SetWindowPos(window
, 0, 0, 0, 200, 200, SWP_NOMOVE
| SWP_NOZORDER
);
3132 ok(ret
, "SetWindowPos failed, error %#x.\n", GetLastError());
3134 memset(&mode
, 0, sizeof(mode
));
3135 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3136 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3137 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3139 GetWindowRect(window
, &e
->window_rect
);
3140 GetClientRect(window
, &e
->client_rect
);
3141 *state
= expected_state
;
3144 static void test_fullscreen_resize_target(IDXGISwapChain
*swapchain
,
3145 const struct swapchain_fullscreen_state
*initial_state
)
3147 struct swapchain_fullscreen_state expected_state
;
3148 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3149 DXGI_OUTPUT_DESC output_desc
;
3150 unsigned int i
, mode_count
;
3151 DXGI_MODE_DESC
*modes
;
3152 IDXGIOutput
*target
;
3155 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3156 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3158 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
3159 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
3161 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
3162 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
3163 "Failed to list modes, hr %#x.\n", hr
);
3164 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3166 win_skip("GetDisplayModeList() not supported.\n");
3167 IDXGIOutput_Release(target
);
3171 modes
= heap_calloc(mode_count
, sizeof(*modes
));
3172 ok(!!modes
, "Failed to allocate memory.\n");
3174 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
3175 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
3177 expected_state
= *initial_state
;
3178 for (i
= 0; i
< min(mode_count
, 20); ++i
)
3180 /* FIXME: Modes with scaling aren't fully tested. */
3181 if (!(swapchain_desc
.Flags
& DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
)
3182 && modes
[i
].Scaling
!= DXGI_MODE_SCALING_UNSPECIFIED
)
3185 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3186 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3188 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3189 &swapchain_desc
, &output_desc
.DesktopCoordinates
, modes
[i
].Width
, modes
[i
].Height
, NULL
);
3191 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &modes
[i
]);
3192 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
3193 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3195 skip("Failed to change to video mode %u.\n", i
);
3198 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3200 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3201 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3202 ok(EqualRect(&output_desc
.DesktopCoordinates
, &expected_state
.fullscreen_state
.monitor_rect
),
3203 "Got desktop coordinates %s, expected %s.\n",
3204 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3205 wine_dbgstr_rect(&expected_state
.fullscreen_state
.monitor_rect
));
3209 IDXGIOutput_Release(target
);
3212 static void test_resize_target(IUnknown
*device
, BOOL is_d3d12
)
3214 struct swapchain_fullscreen_state initial_state
, expected_state
;
3215 unsigned int adapter_idx
, output_idx
, test_idx
;
3216 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3217 DXGI_OUTPUT_DESC output_desc
;
3218 IDXGISwapChain
*swapchain
;
3219 IDXGIFactory
*factory
;
3220 IDXGIAdapter
*adapter
;
3221 IDXGIOutput
*output
;
3234 {{ 0, 0}, TRUE
, FALSE
, 0},
3235 {{10, 10}, TRUE
, FALSE
, 0},
3236 {{ 0, 0}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3237 {{10, 10}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3238 {{ 0, 0}, FALSE
, FALSE
, 0},
3239 {{ 0, 0}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3240 {{10, 10}, FALSE
, FALSE
, 0},
3241 {{10, 10}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3242 {{ 0, 0}, FALSE
, TRUE
, 0},
3243 {{ 0, 0}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3244 {{10, 10}, FALSE
, TRUE
, 0},
3245 {{10, 10}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3248 get_factory(device
, is_d3d12
, &factory
);
3250 swapchain_desc
.BufferDesc
.Width
= 800;
3251 swapchain_desc
.BufferDesc
.Height
= 600;
3252 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3253 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3254 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3255 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3256 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3257 swapchain_desc
.SampleDesc
.Count
= 1;
3258 swapchain_desc
.SampleDesc
.Quality
= 0;
3259 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3260 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
3261 swapchain_desc
.Windowed
= TRUE
;
3262 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
3263 swapchain_desc
.Flags
= 0;
3265 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
3268 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
3271 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
3272 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
3275 for (test_idx
= 0; test_idx
< ARRAY_SIZE(tests
); ++test_idx
)
3277 swapchain_desc
.Flags
= tests
[test_idx
].flags
;
3278 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0,
3279 output_desc
.DesktopCoordinates
.left
+ tests
[test_idx
].origin
.x
,
3280 output_desc
.DesktopCoordinates
.top
+ tests
[test_idx
].origin
.y
,
3281 400, 200, 0, 0, 0, 0);
3282 if (tests
[test_idx
].menu
)
3284 HMENU menu_bar
= CreateMenu();
3285 HMENU menu
= CreateMenu();
3286 AppendMenuA(menu_bar
, MF_POPUP
, (UINT_PTR
)menu
, "Menu");
3287 SetMenu(swapchain_desc
.OutputWindow
, menu_bar
);
3290 memset(&initial_state
, 0, sizeof(initial_state
));
3291 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3293 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3294 ok(SUCCEEDED(hr
), "Adapter %u output %u test %u: CreateSwapChain failed, hr %#x.\n",
3295 adapter_idx
, output_idx
, test_idx
, hr
);
3296 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3298 expected_state
= initial_state
;
3299 if (tests
[test_idx
].fullscreen
)
3301 expected_state
.fullscreen
= TRUE
;
3302 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3303 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 800, 600, NULL
);
3304 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
3305 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3306 "Adapter %u output %u test %u: GetContainingOutput failed, hr %#x.\n",
3307 adapter_idx
, output_idx
, test_idx
, hr
);
3308 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3310 win_skip("Adapter %u output %u test %u: GetContainingOutput() not supported.\n",
3311 adapter_idx
, output_idx
, test_idx
);
3312 IDXGISwapChain_Release(swapchain
);
3313 DestroyWindow(swapchain_desc
.OutputWindow
);
3317 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
3318 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
3319 "Adapter %u output %u test %u: SetFullscreenState failed, hr %#x.\n",
3320 adapter_idx
, output_idx
, test_idx
, hr
);
3321 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3323 skip("Adapter %u output %u test %u: Could not change fullscreen state.\n",
3324 adapter_idx
, output_idx
, test_idx
);
3325 IDXGIOutput_Release(expected_state
.target
);
3326 IDXGISwapChain_Release(swapchain
);
3327 DestroyWindow(swapchain_desc
.OutputWindow
);
3331 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3333 hr
= IDXGISwapChain_ResizeTarget(swapchain
, NULL
);
3334 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Adapter %u output %u test %u: Got unexpected hr %#x.\n",
3335 adapter_idx
, output_idx
, test_idx
, hr
);
3336 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3338 if (tests
[test_idx
].fullscreen
)
3340 test_fullscreen_resize_target(swapchain
, &expected_state
);
3342 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3343 ok(SUCCEEDED(hr
), "Adapter %u output %u test %u: SetFullscreenState failed, hr %#x.\n",
3344 adapter_idx
, output_idx
, test_idx
, hr
);
3345 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3346 IDXGIOutput_Release(expected_state
.target
);
3347 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3348 expected_state
= initial_state
;
3352 test_windowed_resize_target(swapchain
, swapchain_desc
.OutputWindow
, &expected_state
);
3354 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3357 refcount
= IDXGISwapChain_Release(swapchain
);
3358 ok(!refcount
, "Adapter %u output %u test %u: IDXGISwapChain has %u references left.\n",
3359 adapter_idx
, output_idx
, test_idx
, refcount
);
3360 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &expected_state
.fullscreen_state
);
3361 DestroyWindow(swapchain_desc
.OutputWindow
);
3363 IDXGIOutput_Release(output
);
3365 IDXGIAdapter_Release(adapter
);
3367 refcount
= IDXGIFactory_Release(factory
);
3368 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
3371 static LRESULT CALLBACK
resize_target_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
3373 IDXGISwapChain
*swapchain
= (IDXGISwapChain
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
3374 DXGI_SWAP_CHAIN_DESC desc
;
3380 ok(!!swapchain
, "GWLP_USERDATA is NULL.\n");
3381 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
3382 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3383 ok(desc
.BufferDesc
.Width
== 800, "Got unexpected buffer width %u.\n", desc
.BufferDesc
.Width
);
3384 ok(desc
.BufferDesc
.Height
== 600, "Got unexpected buffer height %u.\n", desc
.BufferDesc
.Height
);
3388 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
3392 struct window_thread_data
3395 HANDLE window_created
;
3399 static DWORD WINAPI
window_thread(void *data
)
3401 struct window_thread_data
*thread_data
= data
;
3406 memset(&wc
, 0, sizeof(wc
));
3407 wc
.lpfnWndProc
= resize_target_wndproc
;
3408 wc
.lpszClassName
= "dxgi_resize_target_wndproc_wc";
3409 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
3411 thread_data
->window
= CreateWindowA("dxgi_resize_target_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3412 ok(!!thread_data
->window
, "Failed to create window.\n");
3414 ret
= SetEvent(thread_data
->window_created
);
3415 ok(ret
, "Failed to set event, last error %#x.\n", GetLastError());
3419 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3420 DispatchMessageA(&msg
);
3422 ret
= WaitForSingleObject(thread_data
->finished
, 0);
3423 if (ret
!= WAIT_TIMEOUT
)
3426 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for event, ret %#x, last error %#x.\n", ret
, GetLastError());
3428 DestroyWindow(thread_data
->window
);
3429 thread_data
->window
= NULL
;
3431 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
3436 static void test_resize_target_wndproc(void)
3438 struct window_thread_data thread_data
;
3439 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3440 IDXGISwapChain
*swapchain
;
3441 IDXGIFactory
*factory
;
3442 IDXGIAdapter
*adapter
;
3443 DXGI_MODE_DESC mode
;
3444 IDXGIDevice
*device
;
3452 if (!(device
= create_device(0)))
3454 skip("Failed to create device.\n");
3458 memset(&thread_data
, 0, sizeof(thread_data
));
3459 thread_data
.window_created
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3460 ok(!!thread_data
.window_created
, "Failed to create event, last error %#x.\n", GetLastError());
3461 thread_data
.finished
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3462 ok(!!thread_data
.finished
, "Failed to create event, last error %#x.\n", GetLastError());
3464 thread
= CreateThread(NULL
, 0, window_thread
, &thread_data
, 0, NULL
);
3465 ok(!!thread
, "Failed to create thread, last error %#x.\n", GetLastError());
3466 ret
= WaitForSingleObject(thread_data
.window_created
, INFINITE
);
3467 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#x.\n", ret
, GetLastError());
3469 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3470 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
3471 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3472 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
3474 swapchain_desc
.BufferDesc
.Width
= 800;
3475 swapchain_desc
.BufferDesc
.Height
= 600;
3476 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3477 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3478 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3479 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3480 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3481 swapchain_desc
.SampleDesc
.Count
= 1;
3482 swapchain_desc
.SampleDesc
.Quality
= 0;
3483 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3484 swapchain_desc
.BufferCount
= 1;
3485 swapchain_desc
.OutputWindow
= thread_data
.window
;
3486 swapchain_desc
.Windowed
= TRUE
;
3487 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3488 swapchain_desc
.Flags
= 0;
3489 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3490 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
3492 data
= SetWindowLongPtrA(thread_data
.window
, GWLP_USERDATA
, (LONG_PTR
)swapchain
);
3493 ok(!data
, "Got unexpected GWLP_USERDATA %p.\n", (void *)data
);
3495 memset(&mode
, 0, sizeof(mode
));
3498 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3499 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3501 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3502 ok(hr
== S_OK
, "Getswapchain_desc failed, hr %#x.\n", hr
);
3503 ok(swapchain_desc
.BufferDesc
.Width
== 800,
3504 "Got unexpected buffer width %u.\n", swapchain_desc
.BufferDesc
.Width
);
3505 ok(swapchain_desc
.BufferDesc
.Height
== 600,
3506 "Got unexpected buffer height %u.\n", swapchain_desc
.BufferDesc
.Height
);
3508 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
3509 ok(ret
, "Failed to get client rect.\n");
3510 ok(rect
.right
== mode
.Width
&& rect
.bottom
== mode
.Height
,
3511 "Got unexpected client rect %s.\n", wine_dbgstr_rect(&rect
));
3513 refcount
= IDXGISwapChain_Release(swapchain
);
3514 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3516 IDXGIAdapter_Release(adapter
);
3517 refcount
= IDXGIDevice_Release(device
);
3518 ok(!refcount
, "Device has %u references left.\n", refcount
);
3519 refcount
= IDXGIFactory_Release(factory
);
3520 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3522 ret
= SetEvent(thread_data
.finished
);
3523 ok(ret
, "Failed to set event, last error %#x.\n", GetLastError());
3524 ret
= WaitForSingleObject(thread
, INFINITE
);
3525 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#x.\n", ret
, GetLastError());
3526 CloseHandle(thread
);
3527 CloseHandle(thread_data
.window_created
);
3528 CloseHandle(thread_data
.finished
);
3531 static void test_inexact_modes(void)
3533 struct swapchain_fullscreen_state initial_state
, expected_state
;
3534 DXGI_SWAP_CHAIN_DESC swapchain_desc
, result_desc
;
3535 IDXGIOutput
*output
= NULL
;
3536 IDXGISwapChain
*swapchain
;
3537 IDXGIFactory
*factory
;
3538 IDXGIAdapter
*adapter
;
3539 IDXGIDevice
*device
;
3546 unsigned int width
, height
;
3555 if (!(device
= create_device(0)))
3557 skip("Failed to create device.\n");
3561 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3562 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
3564 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3565 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
3567 swapchain_desc
.BufferDesc
.Width
= 800;
3568 swapchain_desc
.BufferDesc
.Height
= 600;
3569 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3570 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3571 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3572 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3573 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3574 swapchain_desc
.SampleDesc
.Count
= 1;
3575 swapchain_desc
.SampleDesc
.Quality
= 0;
3576 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3577 swapchain_desc
.BufferCount
= 1;
3578 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3579 swapchain_desc
.Windowed
= FALSE
;
3580 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3581 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
3583 memset(&initial_state
, 0, sizeof(initial_state
));
3584 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3586 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3587 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3588 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3589 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3590 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3591 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3592 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
3593 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3594 "GetContainingOutput failed, hr %#x.\n", hr
);
3595 refcount
= IDXGISwapChain_Release(swapchain
);
3596 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3597 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3599 win_skip("GetContainingOutput() not supported.\n");
3602 if (result_desc
.Windowed
)
3604 win_skip("Fullscreen not supported.\n");
3608 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
3610 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3612 /* Test CreateSwapChain(). */
3613 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3614 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3615 swapchain_desc
.Windowed
= FALSE
;
3617 expected_state
= initial_state
;
3618 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3619 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
,
3620 sizes
[i
].width
, sizes
[i
].height
, output
);
3622 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3623 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3625 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3626 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3627 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3628 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3629 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3630 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3631 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3633 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3634 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3635 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3637 refcount
= IDXGISwapChain_Release(swapchain
);
3638 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3640 /* Test SetFullscreenState(). */
3641 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3642 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3643 swapchain_desc
.Windowed
= TRUE
;
3645 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3646 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3648 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3649 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3651 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3652 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3653 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3654 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3655 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3656 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3657 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3659 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3660 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3661 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3663 refcount
= IDXGISwapChain_Release(swapchain
);
3664 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3666 /* Test ResizeTarget(). */
3667 swapchain_desc
.BufferDesc
.Width
= 800;
3668 swapchain_desc
.BufferDesc
.Height
= 600;
3669 swapchain_desc
.Windowed
= TRUE
;
3671 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3672 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3674 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3675 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3677 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3678 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3679 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &swapchain_desc
.BufferDesc
);
3680 ok(SUCCEEDED(hr
), "ResizeTarget failed, hr %#x.\n", hr
);
3682 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3683 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3684 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3685 ok(result_desc
.BufferDesc
.Width
== 800, "Got width %u.\n", result_desc
.BufferDesc
.Width
);
3686 ok(result_desc
.BufferDesc
.Height
== 600, "Got height %u.\n", result_desc
.BufferDesc
.Height
);
3688 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3689 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3690 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3692 refcount
= IDXGISwapChain_Release(swapchain
);
3693 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3698 IDXGIOutput_Release(output
);
3699 IDXGIAdapter_Release(adapter
);
3700 refcount
= IDXGIDevice_Release(device
);
3701 ok(!refcount
, "Device has %u references left.\n", refcount
);
3702 refcount
= IDXGIFactory_Release(factory
);
3703 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3704 DestroyWindow(swapchain_desc
.OutputWindow
);
3707 static void test_create_factory(void)
3713 iface
= (void *)0xdeadbeef;
3714 hr
= CreateDXGIFactory(&IID_IDXGIDevice
, (void **)&iface
);
3715 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3716 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3718 hr
= CreateDXGIFactory(&IID_IUnknown
, (void **)&iface
);
3719 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr
);
3720 IUnknown_Release(iface
);
3722 hr
= CreateDXGIFactory(&IID_IDXGIObject
, (void **)&iface
);
3723 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr
);
3724 IUnknown_Release(iface
);
3726 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&iface
);
3727 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr
);
3728 check_interface(iface
, &IID_IDXGIFactory1
, FALSE
, FALSE
);
3729 IUnknown_Release(iface
);
3731 iface
= (void *)0xdeadbeef;
3732 hr
= CreateDXGIFactory(&IID_IDXGIFactory1
, (void **)&iface
);
3733 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3734 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3737 hr
= CreateDXGIFactory(&IID_IDXGIFactory2
, (void **)&iface
);
3738 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3739 "Got unexpected hr %#x.\n", hr
);
3742 refcount
= IUnknown_Release(iface
);
3743 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3746 if (!pCreateDXGIFactory1
)
3748 win_skip("CreateDXGIFactory1 not available.\n");
3752 iface
= (void *)0xdeadbeef;
3753 hr
= pCreateDXGIFactory1(&IID_IDXGIDevice
, (void **)&iface
);
3754 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3755 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3757 hr
= pCreateDXGIFactory1(&IID_IUnknown
, (void **)&iface
);
3758 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr
);
3759 IUnknown_Release(iface
);
3761 hr
= pCreateDXGIFactory1(&IID_IDXGIObject
, (void **)&iface
);
3762 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr
);
3763 IUnknown_Release(iface
);
3765 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory
, (void **)&iface
);
3766 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr
);
3767 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3768 refcount
= IUnknown_Release(iface
);
3769 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3771 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory1
, (void **)&iface
);
3772 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr
);
3773 IUnknown_Release(iface
);
3776 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory2
, (void **)&iface
);
3777 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3778 "Got unexpected hr %#x.\n", hr
);
3781 refcount
= IUnknown_Release(iface
);
3782 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3785 if (!pCreateDXGIFactory2
)
3787 win_skip("CreateDXGIFactory2 not available.\n");
3791 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory3
, (void **)&iface
);
3792 ok(hr
== S_OK
, "Failed to create factory, hr %#x.\n", hr
);
3793 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3794 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3795 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3796 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3797 /* Not available on all Windows versions. */
3798 check_interface(iface
, &IID_IDXGIFactory4
, TRUE
, TRUE
);
3799 check_interface(iface
, &IID_IDXGIFactory5
, TRUE
, TRUE
);
3800 refcount
= IUnknown_Release(iface
);
3801 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3803 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory
, (void **)&iface
);
3804 ok(hr
== S_OK
, "Failed to create factory, hr %#x.\n", hr
);
3805 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3806 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3807 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3808 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3809 refcount
= IUnknown_Release(iface
);
3810 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3813 static void test_private_data(void)
3815 ULONG refcount
, expected_refcount
;
3816 IDXGIDevice
*device
;
3818 IDXGIDevice
*test_object
;
3820 static const DWORD data
[] = {1, 2, 3, 4};
3822 static const GUID dxgi_private_data_test_guid
=
3827 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
3829 static const GUID dxgi_private_data_test_guid2
=
3834 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
3837 if (!(device
= create_device(0)))
3839 skip("Failed to create device.\n");
3843 test_object
= create_device(0);
3845 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
3846 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
3847 * NULL interface is not considered a clear but as setting an interface pointer that
3848 * happens to be NULL. */
3849 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 0, NULL
);
3850 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3851 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3852 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3853 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3854 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3855 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3856 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3858 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3859 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3860 size
= sizeof(ptr
) * 2;
3861 ptr
= (IUnknown
*)0xdeadbeef;
3862 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3863 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3864 ok(!ptr
, "Got unexpected pointer %p.\n", ptr
);
3865 ok(size
== sizeof(IUnknown
*), "Got unexpected size %u.\n", size
);
3867 refcount
= get_refcount(test_object
);
3868 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3869 (IUnknown
*)test_object
);
3870 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3871 expected_refcount
= refcount
+ 1;
3872 refcount
= get_refcount(test_object
);
3873 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3874 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3875 (IUnknown
*)test_object
);
3876 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3877 refcount
= get_refcount(test_object
);
3878 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3880 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3881 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3882 expected_refcount
--;
3883 refcount
= get_refcount(test_object
);
3884 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3886 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3887 (IUnknown
*)test_object
);
3888 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3889 size
= sizeof(data
);
3890 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, size
, data
);
3891 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3892 refcount
= get_refcount(test_object
);
3893 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3894 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3895 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3896 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3897 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3899 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3900 (IUnknown
*)test_object
);
3901 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3902 expected_refcount
++;
3903 size
= 2 * sizeof(ptr
);
3905 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3906 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3907 ok(size
== sizeof(test_object
), "Got unexpected size %u.\n", size
);
3908 expected_refcount
++;
3909 refcount
= get_refcount(test_object
);
3910 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3912 IUnknown_Release(ptr
);
3913 expected_refcount
--;
3915 ptr
= (IUnknown
*)0xdeadbeef;
3917 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3918 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3919 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3920 size
= 2 * sizeof(ptr
);
3921 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3922 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3923 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3924 refcount
= get_refcount(test_object
);
3925 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3928 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3929 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
3930 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3931 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3932 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, NULL
, NULL
);
3933 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
3935 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, &size
, &ptr
);
3936 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
3937 ok(size
== 0, "Got unexpected size %u.\n", size
);
3938 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3939 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, NULL
, &ptr
);
3940 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
3941 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3943 refcount
= IDXGIDevice_Release(device
);
3944 ok(!refcount
, "Device has %u references left.\n", refcount
);
3945 refcount
= IDXGIDevice_Release(test_object
);
3946 ok(!refcount
, "Test object has %u references left.\n", refcount
);
3949 #define check_surface_desc(a, b) check_surface_desc_(__LINE__, a, b)
3950 static void check_surface_desc_(unsigned int line
, IDXGISurface
*surface
,
3951 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3953 DXGI_SURFACE_DESC surface_desc
;
3956 hr
= IDXGISurface_GetDesc(surface
, &surface_desc
);
3957 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get surface desc, hr %#x.\n", hr
);
3958 ok_(__FILE__
, line
)(surface_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3959 "Got Width %u, expected %u.\n", surface_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3960 ok_(__FILE__
, line
)(surface_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3961 "Got Height %u, expected %u.\n", surface_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3962 ok_(__FILE__
, line
)(surface_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3963 "Got Format %#x, expected %#x.\n", surface_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3964 ok_(__FILE__
, line
)(surface_desc
.SampleDesc
.Count
== 1,
3965 "Got unexpected SampleDesc.Count %u.\n", surface_desc
.SampleDesc
.Count
);
3966 ok_(__FILE__
, line
)(!surface_desc
.SampleDesc
.Quality
,
3967 "Got unexpected SampleDesc.Quality %u.\n", surface_desc
.SampleDesc
.Quality
);
3970 #define check_texture_desc(a, b) check_texture_desc_(__LINE__, a, b)
3971 static void check_texture_desc_(unsigned int line
, ID3D10Texture2D
*texture
,
3972 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3974 D3D10_TEXTURE2D_DESC texture_desc
;
3976 ID3D10Texture2D_GetDesc(texture
, &texture_desc
);
3977 ok_(__FILE__
, line
)(texture_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3978 "Got Width %u, expected %u.\n", texture_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3979 ok_(__FILE__
, line
)(texture_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3980 "Got Height %u, expected %u.\n", texture_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3981 ok_(__FILE__
, line
)(texture_desc
.MipLevels
== 1, "Got unexpected MipLevels %u.\n", texture_desc
.MipLevels
);
3982 ok_(__FILE__
, line
)(texture_desc
.ArraySize
== 1, "Got unexpected ArraySize %u.\n", texture_desc
.ArraySize
);
3983 ok_(__FILE__
, line
)(texture_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3984 "Got Format %#x, expected %#x.\n", texture_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3985 ok_(__FILE__
, line
)(texture_desc
.SampleDesc
.Count
== 1,
3986 "Got unexpected SampleDesc.Count %u.\n", texture_desc
.SampleDesc
.Count
);
3987 ok_(__FILE__
, line
)(!texture_desc
.SampleDesc
.Quality
,
3988 "Got unexpected SampleDesc.Quality %u.\n", texture_desc
.SampleDesc
.Quality
);
3989 ok_(__FILE__
, line
)(texture_desc
.Usage
== D3D10_USAGE_DEFAULT
,
3990 "Got unexpected Usage %#x.\n", texture_desc
.Usage
);
3991 ok_(__FILE__
, line
)(texture_desc
.BindFlags
== D3D10_BIND_RENDER_TARGET
,
3992 "Got unexpected BindFlags %#x.\n", texture_desc
.BindFlags
);
3993 ok_(__FILE__
, line
)(!texture_desc
.CPUAccessFlags
,
3994 "Got unexpected CPUAccessFlags %#x.\n", texture_desc
.CPUAccessFlags
);
3995 ok_(__FILE__
, line
)(!texture_desc
.MiscFlags
, "Got unexpected MiscFlags %#x.\n", texture_desc
.MiscFlags
);
3998 #define check_resource_desc(a, b) check_resource_desc_(__LINE__, a, b)
3999 static void check_resource_desc_(unsigned int line
, ID3D12Resource
*resource
,
4000 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
4002 D3D12_RESOURCE_DESC resource_desc
;
4004 resource_desc
= ID3D12Resource_GetDesc(resource
);
4005 ok_(__FILE__
, line
)(resource_desc
.Dimension
== D3D12_RESOURCE_DIMENSION_TEXTURE2D
,
4006 "Got unexpected Dimension %#x.\n", resource_desc
.Dimension
);
4007 ok_(__FILE__
, line
)(resource_desc
.Width
== swapchain_desc
->BufferDesc
.Width
, "Got Width %s, expected %u.\n",
4008 wine_dbgstr_longlong(resource_desc
.Width
), swapchain_desc
->BufferDesc
.Width
);
4009 ok_(__FILE__
, line
)(resource_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
4010 "Got Height %u, expected %u.\n", resource_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
4011 ok_(__FILE__
, line
)(resource_desc
.DepthOrArraySize
== 1,
4012 "Got unexpected DepthOrArraySize %u.\n", resource_desc
.DepthOrArraySize
);
4013 ok_(__FILE__
, line
)(resource_desc
.MipLevels
== 1,
4014 "Got unexpected MipLevels %u.\n", resource_desc
.MipLevels
);
4015 ok_(__FILE__
, line
)(resource_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
4016 "Got Format %#x, expected %#x.\n", resource_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
4017 ok_(__FILE__
, line
)(resource_desc
.SampleDesc
.Count
== 1,
4018 "Got unexpected SampleDesc.Count %u.\n", resource_desc
.SampleDesc
.Count
);
4019 ok_(__FILE__
, line
)(!resource_desc
.SampleDesc
.Quality
,
4020 "Got unexpected SampleDesc.Quality %u.\n", resource_desc
.SampleDesc
.Quality
);
4021 ok_(__FILE__
, line
)(resource_desc
.Layout
== D3D12_TEXTURE_LAYOUT_UNKNOWN
,
4022 "Got unexpected Layout %#x.\n", resource_desc
.Layout
);
4025 static void test_swapchain_resize(IUnknown
*device
, BOOL is_d3d12
)
4027 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4028 DXGI_SWAP_EFFECT swap_effect
;
4029 IDXGISwapChain3
*swapchain3
;
4030 IUnknown
*present_queue
[2];
4031 IDXGISwapChain
*swapchain
;
4032 ID3D12Resource
*resource
;
4033 ID3D10Texture2D
*texture
;
4034 HRESULT hr
, expected_hr
;
4035 IDXGISurface
*surface
;
4036 IDXGIFactory
*factory
;
4037 RECT client_rect
, r
;
4043 get_factory(device
, is_d3d12
, &factory
);
4045 window
= create_window();
4046 ret
= GetClientRect(window
, &client_rect
);
4047 ok(ret
, "Failed to get client rect.\n");
4049 swap_effect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4051 swapchain_desc
.BufferDesc
.Width
= 640;
4052 swapchain_desc
.BufferDesc
.Height
= 480;
4053 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4054 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
4055 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4056 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4057 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4058 swapchain_desc
.SampleDesc
.Count
= 1;
4059 swapchain_desc
.SampleDesc
.Quality
= 0;
4060 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4061 swapchain_desc
.BufferCount
= 2;
4062 swapchain_desc
.OutputWindow
= window
;
4063 swapchain_desc
.Windowed
= TRUE
;
4064 swapchain_desc
.SwapEffect
= swap_effect
;
4065 swapchain_desc
.Flags
= 0;
4067 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4068 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
4069 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4070 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4071 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4072 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4073 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4074 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4075 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4076 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4077 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4078 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4079 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4081 ret
= GetClientRect(window
, &r
);
4082 ok(ret
, "Failed to get client rect.\n");
4083 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4084 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4086 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4087 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4088 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4089 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4090 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4091 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4092 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4093 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4094 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4095 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4096 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4097 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4098 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4099 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4100 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4101 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4102 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4103 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4104 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4105 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4106 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4107 ok(!swapchain_desc
.SampleDesc
.Quality
,
4108 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4109 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4110 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4111 ok(swapchain_desc
.BufferCount
== 2,
4112 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4113 ok(swapchain_desc
.OutputWindow
== window
,
4114 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4115 ok(swapchain_desc
.Windowed
,
4116 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4117 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4118 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4119 ok(!swapchain_desc
.Flags
,
4120 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4123 check_surface_desc(surface
, &swapchain_desc
);
4125 check_texture_desc(texture
, &swapchain_desc
);
4127 check_resource_desc(resource
, &swapchain_desc
);
4129 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4130 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4132 ret
= GetClientRect(window
, &r
);
4133 ok(ret
, "Failed to get client rect.\n");
4134 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4135 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4137 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4138 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4139 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4140 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4141 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4142 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4143 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4144 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4145 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4146 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4147 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4148 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4149 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4150 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4151 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4152 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4153 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4154 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4155 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4156 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4157 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4158 ok(!swapchain_desc
.SampleDesc
.Quality
,
4159 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4160 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4161 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4162 ok(swapchain_desc
.BufferCount
== 2,
4163 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4164 ok(swapchain_desc
.OutputWindow
== window
,
4165 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4166 ok(swapchain_desc
.Windowed
,
4167 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4168 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4169 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4170 ok(!swapchain_desc
.Flags
,
4171 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4175 check_surface_desc(surface
, &swapchain_desc
);
4176 IDXGISurface_Release(surface
);
4180 check_texture_desc(texture
, &swapchain_desc
);
4181 ID3D10Texture2D_Release(texture
);
4185 check_resource_desc(resource
, &swapchain_desc
);
4186 ID3D12Resource_Release(resource
);
4189 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4190 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4191 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4192 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4193 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4194 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4195 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4196 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4197 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4198 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4199 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4200 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4201 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4203 ret
= GetClientRect(window
, &r
);
4204 ok(ret
, "Failed to get client rect.\n");
4205 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4206 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4208 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4209 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4210 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4211 ok(swapchain_desc
.BufferDesc
.Width
== 320,
4212 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4213 ok(swapchain_desc
.BufferDesc
.Height
== 240,
4214 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4215 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4216 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4217 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4218 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4219 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4220 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4221 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4222 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4223 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4224 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4225 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4226 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4227 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4228 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4229 ok(!swapchain_desc
.SampleDesc
.Quality
,
4230 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4231 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4232 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4233 ok(swapchain_desc
.BufferCount
== 2,
4234 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4235 ok(swapchain_desc
.OutputWindow
== window
,
4236 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4237 ok(swapchain_desc
.Windowed
,
4238 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4239 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4240 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4241 ok(!swapchain_desc
.Flags
,
4242 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4246 check_surface_desc(surface
, &swapchain_desc
);
4247 IDXGISurface_Release(surface
);
4251 check_texture_desc(texture
, &swapchain_desc
);
4252 ID3D10Texture2D_Release(texture
);
4256 check_resource_desc(resource
, &swapchain_desc
);
4257 ID3D12Resource_Release(resource
);
4260 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4261 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4263 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4264 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4265 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4266 ok(swapchain_desc
.BufferDesc
.Width
== client_rect
.right
- client_rect
.left
,
4267 "Got unexpected BufferDesc.Width %u, expected %u.\n",
4268 swapchain_desc
.BufferDesc
.Width
, client_rect
.right
- client_rect
.left
);
4269 ok(swapchain_desc
.BufferDesc
.Height
== client_rect
.bottom
- client_rect
.top
,
4270 "Got unexpected bufferDesc.Height %u, expected %u.\n",
4271 swapchain_desc
.BufferDesc
.Height
, client_rect
.bottom
- client_rect
.top
);
4272 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4273 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4274 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4275 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4276 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4277 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4278 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4279 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4280 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4281 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4282 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4283 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4284 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4285 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4286 ok(!swapchain_desc
.SampleDesc
.Quality
,
4287 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4288 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4289 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4290 ok(swapchain_desc
.BufferCount
== 2,
4291 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4292 ok(swapchain_desc
.OutputWindow
== window
,
4293 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4294 ok(swapchain_desc
.Windowed
,
4295 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4296 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4297 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4298 ok(!swapchain_desc
.Flags
,
4299 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4303 present_queue
[0] = device
;
4304 present_queue
[1] = device
;
4305 if (IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
) == E_NOINTERFACE
)
4307 skip("IDXGISwapChain3 is not supported.\n");
4311 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4312 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4313 IDXGISwapChain3_Release(swapchain3
);
4317 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4318 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4319 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, present_queue
);
4320 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4321 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4322 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4323 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4324 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4327 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4328 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4329 /* Windows validates node masks even when the buffer count is zero. It defaults to the current buffer count.
4330 * NULL queues cause some Windows versions to crash. */
4331 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4332 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4333 IDXGISwapChain3_Release(swapchain3
);
4336 IDXGISwapChain_Release(swapchain
);
4337 DestroyWindow(window
);
4338 refcount
= IDXGIFactory_Release(factory
);
4339 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
4342 static void test_swapchain_parameters(void)
4344 DXGI_USAGE usage
, expected_usage
, broken_usage
;
4345 D3D10_TEXTURE2D_DESC d3d10_texture_desc
;
4346 D3D11_TEXTURE2D_DESC d3d11_texture_desc
;
4347 unsigned int expected_bind_flags
;
4348 ID3D10Texture2D
*d3d10_texture
;
4349 ID3D11Texture2D
*d3d11_texture
;
4350 DXGI_SWAP_CHAIN_DESC desc
;
4351 IDXGISwapChain
*swapchain
;
4352 IDXGIResource
*resource
;
4353 IDXGIAdapter
*adapter
;
4354 IDXGIFactory
*factory
;
4355 IDXGIDevice
*device
;
4366 DXGI_SWAP_EFFECT swap_effect
;
4367 HRESULT hr
, vista_hr
;
4368 UINT highest_accessible_buffer
;
4373 {TRUE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4374 {TRUE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4375 {TRUE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4376 {TRUE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4377 {TRUE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4379 {TRUE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4380 {TRUE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4381 {TRUE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4382 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4383 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4385 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4386 {TRUE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4387 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4388 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4389 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4391 {TRUE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4392 {TRUE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4393 {TRUE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4394 {TRUE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4395 {TRUE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4397 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4398 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4399 {TRUE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4400 {FALSE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4401 {FALSE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4403 {FALSE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4404 {FALSE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4405 {FALSE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4406 {FALSE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4407 {FALSE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4409 {FALSE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4410 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4411 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4412 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4413 {FALSE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4415 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4416 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4417 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4418 {FALSE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4419 {FALSE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4421 {FALSE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4422 {FALSE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4423 {FALSE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4424 {FALSE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4425 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4427 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4429 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
4430 * process. Disable it for now.
4431 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
4434 /* The following tests crash on Win10 1909
4435 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4436 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4437 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4438 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4439 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4440 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4441 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4442 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4443 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4446 static const DXGI_USAGE usage_tests
[] =
4449 DXGI_USAGE_BACK_BUFFER
,
4450 DXGI_USAGE_SHADER_INPUT
,
4451 DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4452 DXGI_USAGE_DISCARD_ON_PRESENT
,
4453 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
,
4454 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4455 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4456 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4457 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4460 if (!(device
= create_device(0)))
4462 skip("Failed to create device.\n");
4465 window
= create_window();
4467 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
4468 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
4470 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
4471 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
4472 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
4473 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
4474 IDXGIAdapter_Release(adapter
);
4476 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
4478 memset(&desc
, 0, sizeof(desc
));
4479 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4480 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4481 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4482 desc
.SampleDesc
.Count
= 1;
4483 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4484 desc
.OutputWindow
= window
;
4486 desc
.Windowed
= tests
[i
].windowed
;
4487 desc
.BufferCount
= tests
[i
].buffer_count
;
4488 desc
.SwapEffect
= tests
[i
].swap_effect
;
4490 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4491 ok(hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].vista_hr
)
4492 || (SUCCEEDED(tests
[i
].hr
) && hr
== DXGI_STATUS_OCCLUDED
),
4493 "Got unexpected hr %#x, test %u.\n", hr
, i
);
4497 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4498 todo_wine
ok(SUCCEEDED(hr
), "GetBuffer(0) failed, hr %#x, test %u.\n", hr
, i
);
4501 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4502 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
4504 IDXGISwapChain_Release(swapchain
);
4508 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4509 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4510 ok(SUCCEEDED(hr
), "Failed to get resource usage, hr %#x, test %u.\n", hr
, i
);
4511 ok((usage
& expected_usage
) == expected_usage
, "Got usage %x, expected %x, test %u.\n",
4512 usage
, expected_usage
, i
);
4514 IDXGIResource_Release(resource
);
4516 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4517 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4519 for (j
= 1; j
<= tests
[i
].highest_accessible_buffer
; j
++)
4521 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4522 ok(SUCCEEDED(hr
), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr
, i
, j
);
4524 /* Buffers > 0 are supposed to be read only. This is the case except that in
4525 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
4526 * writable. This is not the case if an unsupported refresh rate is passed
4527 * for some reason, probably because the invalid refresh rate triggers a
4528 * kinda-sorta windowed mode.
4530 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
4533 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
4534 * the draw on the screen right away (Aero on or off doesn't matter), but
4535 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
4537 * Note that if the application doesn't have focused creating a fullscreen
4538 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
4539 * so use the Windowed property of the swapchain that was actually created. */
4540 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_READ_ONLY
;
4541 broken_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4543 if (desc
.Windowed
|| j
< tests
[i
].highest_accessible_buffer
)
4544 broken_usage
|= DXGI_USAGE_READ_ONLY
;
4546 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4547 ok(SUCCEEDED(hr
), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr
, i
, j
);
4548 ok(usage
== expected_usage
|| broken(usage
== broken_usage
),
4549 "Got usage %x, expected %x, test %u, buffer %u.\n",
4550 usage
, expected_usage
, i
, j
);
4552 IDXGIResource_Release(resource
);
4554 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4555 ok(hr
== DXGI_ERROR_INVALID_CALL
, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j
, hr
, i
);
4557 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4558 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
4560 IDXGISwapChain_Release(swapchain
);
4563 for (i
= 0; i
< ARRAY_SIZE(usage_tests
); ++i
)
4565 usage
= usage_tests
[i
];
4567 memset(&desc
, 0, sizeof(desc
));
4568 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4569 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4570 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4571 desc
.SampleDesc
.Count
= 1;
4572 desc
.BufferUsage
= usage
;
4573 desc
.BufferCount
= 1;
4574 desc
.OutputWindow
= window
;
4575 desc
.Windowed
= TRUE
;
4576 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4577 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4578 ok(hr
== S_OK
, "Got unexpected hr %#x, test %u.\n", hr
, i
);
4580 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4581 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x, test %u.\n", hr
, i
);
4582 todo_wine_if(usage
& ~(DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_SHADER_INPUT
))
4583 ok(desc
.BufferUsage
== usage
, "Got usage %#x, expected %#x, test %u.\n", desc
.BufferUsage
, usage
, i
);
4585 expected_bind_flags
= 0;
4586 if (usage
& DXGI_USAGE_RENDER_TARGET_OUTPUT
)
4587 expected_bind_flags
|= D3D11_BIND_RENDER_TARGET
;
4588 if (usage
& DXGI_USAGE_SHADER_INPUT
)
4589 expected_bind_flags
|= D3D11_BIND_SHADER_RESOURCE
;
4591 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&d3d10_texture
);
4592 ok(hr
== S_OK
, "Failed to get d3d10 texture, hr %#x, test %u.\n", hr
, i
);
4593 ID3D10Texture2D_GetDesc(d3d10_texture
, &d3d10_texture_desc
);
4594 ok(d3d10_texture_desc
.BindFlags
== expected_bind_flags
,
4595 "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
4596 d3d10_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4597 ID3D10Texture2D_Release(d3d10_texture
);
4599 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D11Texture2D
, (void **)&d3d11_texture
);
4600 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get d3d11 texture, hr %#x, test %u.\n", hr
, i
);
4603 ID3D11Texture2D_GetDesc(d3d11_texture
, &d3d11_texture_desc
);
4604 ok(d3d11_texture_desc
.BindFlags
== expected_bind_flags
,
4605 "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
4606 d3d11_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4607 ID3D11Texture2D_Release(d3d11_texture
);
4610 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4611 todo_wine
ok(hr
== S_OK
, "Failed to get buffer, hr %#x, test %u.\n", hr
, i
);
4614 IDXGISwapChain_Release(swapchain
);
4617 expected_usage
= usage
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
;
4618 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4619 ok(hr
== S_OK
, "Failed to get resource usage, hr %#x, test %u.\n", hr
, i
);
4620 ok(usage
== expected_usage
, "Got usage %x, expected %x, test %u.\n", usage
, expected_usage
, i
);
4621 IDXGIResource_Release(resource
);
4623 IDXGISwapChain_Release(swapchain
);
4627 memset(&desc
, 0, sizeof(desc
));
4628 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4629 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4630 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4631 desc
.SampleDesc
.Count
= 4;
4632 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4633 desc
.BufferCount
= 4;
4634 desc
.OutputWindow
= window
;
4635 desc
.Windowed
= TRUE
;
4636 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
;
4637 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4638 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4639 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
4640 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4641 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4642 if (check_multisample_quality_levels(device
, desc
.BufferDesc
.Format
, desc
.SampleDesc
.Count
))
4644 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4645 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4646 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4647 IDXGISwapChain_Release(swapchain
);
4648 desc
.SwapEffect
= DXGI_SWAP_EFFECT_SEQUENTIAL
;
4649 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4650 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4651 IDXGISwapChain_Release(swapchain
);
4655 skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM.\n");
4658 IDXGIFactory_Release(factory
);
4659 IUnknown_Release(obj
);
4660 refcount
= IDXGIDevice_Release(device
);
4661 ok(!refcount
, "Device has %u references left.\n", refcount
);
4662 DestroyWindow(window
);
4665 static void test_swapchain_present(IUnknown
*device
, BOOL is_d3d12
)
4667 static const DWORD flags
[] = {0, DXGI_PRESENT_TEST
};
4668 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4669 IDXGISwapChain
*swapchain
;
4670 IDXGIFactory
*factory
;
4671 IDXGIOutput
*output
;
4677 get_factory(device
, is_d3d12
, &factory
);
4679 swapchain_desc
.BufferDesc
.Width
= 800;
4680 swapchain_desc
.BufferDesc
.Height
= 600;
4681 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4682 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4683 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4684 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4685 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4686 swapchain_desc
.SampleDesc
.Count
= 1;
4687 swapchain_desc
.SampleDesc
.Quality
= 0;
4688 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4689 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
4690 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
4691 swapchain_desc
.Windowed
= TRUE
;
4692 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4693 swapchain_desc
.Flags
= 0;
4695 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4696 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
4698 for (i
= 0; i
< 10; ++i
)
4700 hr
= IDXGISwapChain_Present(swapchain
, i
, 0);
4701 ok(hr
== (i
<= 4 ? S_OK
: DXGI_ERROR_INVALID_CALL
),
4702 "Got unexpected hr %#x for sync interval %u.\n", hr
, i
);
4704 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4705 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4707 for (i
= 0; i
< ARRAY_SIZE(flags
); ++i
)
4709 HWND occluding_window
= CreateWindowA("static", "occluding_window",
4710 WS_POPUP
| WS_VISIBLE
, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
4712 /* Another window covers the swapchain window. Not reported as occluded. */
4713 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4714 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4716 /* Minimised window. */
4717 ShowWindow(swapchain_desc
.OutputWindow
, SW_MINIMIZE
);
4718 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4719 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4720 ShowWindow(swapchain_desc
.OutputWindow
, SW_NORMAL
);
4722 /* Hidden window. */
4723 ShowWindow(swapchain_desc
.OutputWindow
, SW_HIDE
);
4724 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4725 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4726 ShowWindow(swapchain_desc
.OutputWindow
, SW_SHOW
);
4727 DestroyWindow(occluding_window
);
4729 /* Test that IDXGIOutput_ReleaseOwnership() makes the swapchain exit
4731 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4732 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
4733 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
4734 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
4736 skip("Test %u: Could not change fullscreen state.\n", i
);
4740 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4741 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4742 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4743 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4744 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4747 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
4748 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4749 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4750 ok(!!output
, "Test %u: Got unexpected output.\n", i
);
4753 IDXGIOutput_ReleaseOwnership(output
);
4754 /* Still fullscreen. */
4756 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4757 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4758 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4759 /* Calling IDXGISwapChain_Present() will exit fullscreen. */
4760 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4761 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4763 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4764 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4765 /* Now fullscreen mode is exited. */
4766 if (!flags
[i
] && !is_d3d12
)
4767 /* Still fullscreen on vista and 2008. */
4768 todo_wine
ok(!fullscreen
|| broken(fullscreen
), "Test %u: Got unexpected fullscreen status.\n", i
);
4770 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4772 IDXGIOutput_Release(output
);
4774 /* Test creating a window when swapchain is in fullscreen.
4776 * The window should break the swapchain out of fullscreen mode on
4777 * d3d10/11. D3d12 is different, a new occluding window doesn't break
4778 * the swapchain out of fullscreen because d3d12 fullscreen swapchains
4779 * don't take exclusive ownership over the output, nor do they disable
4780 * compositing. D3d12 fullscreen mode acts just like borderless
4781 * fullscreen window mode. */
4782 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4783 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4785 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4786 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4787 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4788 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4789 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4790 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4791 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4793 occluding_window
= CreateWindowA("static", "occluding_window", WS_POPUP
, 0, 0, 400, 200, 0, 0, 0, 0);
4794 /* An invisible window doesn't cause the swapchain to exit fullscreen
4796 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4797 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4798 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4799 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4801 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4802 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4803 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4804 /* A visible, but with bottom z-order window still causes the
4805 * swapchain to exit fullscreen mode. */
4806 SetWindowPos(occluding_window
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
4807 ShowWindow(occluding_window
, SW_SHOW
);
4808 /* Fullscreen mode takes a while to exit. */
4810 wait_fullscreen_state(swapchain
, FALSE
, TRUE
);
4812 /* No longer fullscreen before calling IDXGISwapChain_Present() except
4815 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4816 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4817 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4818 "Test %u: Got unexpected fullscreen status.\n", i
);
4820 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4821 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4822 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4823 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4824 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4827 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4828 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4829 if (flags
[i
] == DXGI_PRESENT_TEST
)
4830 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4831 "Test %u: Got unexpected fullscreen status.\n", i
);
4833 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4835 /* Even though d3d12 doesn't exit fullscreen, a
4836 * IDXGISwapChain_ResizeBuffers() is still needed for subsequent
4837 * IDXGISwapChain_Present() calls to work, otherwise they will return
4838 * DXGI_ERROR_INVALID_CALL */
4839 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4840 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4841 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4842 if (flags
[i
] == DXGI_PRESENT_TEST
)
4843 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4844 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4846 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4848 /* Trying to break out of fullscreen mode again. This time, don't call
4849 * IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */
4850 ShowWindow(occluding_window
, SW_HIDE
);
4851 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4852 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4853 ShowWindow(occluding_window
, SW_SHOW
);
4855 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4856 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4857 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4858 /* hr == S_OK on vista and 2008 */
4859 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4860 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4862 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4863 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4864 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4865 if (flags
[i
] == DXGI_PRESENT_TEST
)
4867 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4868 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4869 /* IDXGISwapChain_Present() without flags refreshes the occlusion
4871 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4872 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4873 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4874 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4875 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4876 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4877 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4878 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
4879 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4883 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4886 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4887 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4888 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4890 DestroyWindow(occluding_window
);
4892 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4893 todo_wine_if(!is_d3d12
) ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4894 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4895 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4897 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4898 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4899 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4900 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4903 wait_device_idle(device
);
4905 IDXGISwapChain_Release(swapchain
);
4906 DestroyWindow(swapchain_desc
.OutputWindow
);
4907 refcount
= IDXGIFactory_Release(factory
);
4908 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
4911 static void test_swapchain_backbuffer_index(IUnknown
*device
, BOOL is_d3d12
)
4913 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4914 unsigned int index
, expected_index
;
4915 IDXGISwapChain3
*swapchain3
;
4916 IDXGISwapChain
*swapchain
;
4917 HRESULT hr
, expected_hr
;
4918 IDXGIFactory
*factory
;
4924 static const DXGI_SWAP_EFFECT swap_effects
[] =
4926 DXGI_SWAP_EFFECT_DISCARD
,
4927 DXGI_SWAP_EFFECT_SEQUENTIAL
,
4928 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
,
4929 DXGI_SWAP_EFFECT_FLIP_DISCARD
,
4932 get_factory(device
, is_d3d12
, &factory
);
4934 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4935 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4936 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4937 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4938 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4939 swapchain_desc
.SampleDesc
.Count
= 1;
4940 swapchain_desc
.SampleDesc
.Quality
= 0;
4941 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4942 swapchain_desc
.BufferCount
= 4;
4943 swapchain_desc
.OutputWindow
= create_window();
4944 swapchain_desc
.Windowed
= TRUE
;
4945 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4946 swapchain_desc
.Flags
= 0;
4948 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
4949 ok(ret
, "Failed to get client rect.\n");
4950 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
4951 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
4953 for (i
= 0; i
< ARRAY_SIZE(swap_effects
); ++i
)
4955 swapchain_desc
.SwapEffect
= swap_effects
[i
];
4956 expected_hr
= is_d3d12
&& !is_flip_model(swap_effects
[i
]) ? DXGI_ERROR_INVALID_CALL
: S_OK
;
4957 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4958 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4962 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
);
4963 if (hr
== E_NOINTERFACE
)
4965 skip("IDXGISwapChain3 is not supported.\n");
4966 IDXGISwapChain_Release(swapchain
);
4970 for (j
= 0; j
< 2 * swapchain_desc
.BufferCount
; ++j
)
4972 index
= IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3
);
4973 expected_index
= is_d3d12
? j
% swapchain_desc
.BufferCount
: 0;
4974 ok(index
== expected_index
, "Got back buffer index %u, expected %u.\n", index
, expected_index
);
4975 hr
= IDXGISwapChain3_Present(swapchain3
, 0, 0);
4976 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4979 wait_device_idle(device
);
4981 IDXGISwapChain3_Release(swapchain3
);
4982 refcount
= IDXGISwapChain_Release(swapchain
);
4983 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
4987 DestroyWindow(swapchain_desc
.OutputWindow
);
4988 refcount
= IDXGIFactory_Release(factory
);
4989 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
4992 static void test_swapchain_formats(IUnknown
*device
, BOOL is_d3d12
)
4994 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4995 IDXGISwapChain
*swapchain
;
4996 HRESULT hr
, expected_hr
;
4997 IDXGIFactory
*factory
;
5006 DXGI_SWAP_EFFECT swap_effect
;
5011 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_DISCARD
, FALSE
},
5012 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_SEQUENTIAL
, FALSE
},
5013 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5014 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5015 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5016 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5017 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5018 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5019 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5020 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5021 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5022 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5023 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5024 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5025 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5026 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5027 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5028 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5029 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5030 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5031 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5032 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5033 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5034 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5035 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5036 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5037 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5038 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5039 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5040 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5043 get_factory(device
, is_d3d12
, &factory
);
5045 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5046 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5047 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5048 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5049 swapchain_desc
.SampleDesc
.Count
= 1;
5050 swapchain_desc
.SampleDesc
.Quality
= 0;
5051 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5052 swapchain_desc
.BufferCount
= 4;
5053 swapchain_desc
.OutputWindow
= create_window();
5054 swapchain_desc
.Windowed
= TRUE
;
5055 swapchain_desc
.Flags
= 0;
5057 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
5058 ok(ret
, "Failed to get client rect.\n");
5059 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
5060 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
5062 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
5064 if (is_d3d12
&& !is_flip_model(tests
[i
].swap_effect
))
5067 swapchain_desc
.BufferDesc
.Format
= tests
[i
].format
;
5068 swapchain_desc
.SwapEffect
= tests
[i
].swap_effect
;
5069 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
5070 expected_hr
= tests
[i
].supported
? S_OK
: DXGI_ERROR_INVALID_CALL
;
5071 if (tests
[i
].format
== DXGI_FORMAT_UNKNOWN
&& !is_d3d12
)
5072 expected_hr
= E_INVALIDARG
;
5073 ok(hr
== expected_hr
5074 /* Flip presentation model not supported. */
5075 || broken(hr
== DXGI_ERROR_INVALID_CALL
&& is_flip_model(tests
[i
].swap_effect
) && !is_d3d12
),
5076 "Test %u, d3d12 %#x: Got hr %#x, expected %#x.\n", i
, is_d3d12
, hr
, expected_hr
);
5080 refcount
= IDXGISwapChain_Release(swapchain
);
5081 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
5085 DestroyWindow(swapchain_desc
.OutputWindow
);
5086 refcount
= IDXGIFactory_Release(factory
);
5087 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
5090 static void test_maximum_frame_latency(void)
5092 IDXGIDevice1
*device1
;
5093 IDXGIDevice
*device
;
5098 if (!(device
= create_device(0)))
5100 skip("Failed to create device.\n");
5104 if (SUCCEEDED(IDXGIDevice_QueryInterface(device
, &IID_IDXGIDevice1
, (void **)&device1
)))
5106 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, NULL
);
5107 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5109 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5110 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5111 ok(max_latency
== DEFAULT_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5113 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
);
5114 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5115 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5116 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5117 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5119 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
+ 1);
5120 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5121 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5122 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5123 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5125 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, 0);
5126 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5127 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5128 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5129 /* 0 does not reset to the default frame latency on all Windows versions. */
5130 ok(max_latency
== DEFAULT_FRAME_LATENCY
|| broken(!max_latency
),
5131 "Got unexpected maximum frame latency %u.\n", max_latency
);
5133 IDXGIDevice1_Release(device1
);
5137 win_skip("IDXGIDevice1 is not implemented.\n");
5140 refcount
= IDXGIDevice_Release(device
);
5141 ok(!refcount
, "Device has %u references left.\n", refcount
);
5144 static void test_output_desc(void)
5146 IDXGIAdapter
*adapter
, *adapter2
;
5147 IDXGIOutput
*output
, *output2
;
5148 DXGI_OUTPUT_DESC desc
;
5149 IDXGIFactory
*factory
;
5154 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5155 ok(SUCCEEDED(hr
), "Failed to create DXGI factory, hr %#x.\n", hr
);
5159 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter
);
5160 if (hr
== DXGI_ERROR_NOT_FOUND
)
5162 ok(SUCCEEDED(hr
), "Failed to enumerate adapter %u, hr %#x.\n", i
, hr
);
5164 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter2
);
5165 ok(SUCCEEDED(hr
), "Failed to enumerate adapter %u, hr %#x.\n", i
, hr
);
5166 ok(adapter
!= adapter2
, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter
, adapter2
);
5167 refcount
= get_refcount(adapter
);
5168 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5169 IDXGIAdapter_Release(adapter2
);
5171 refcount
= get_refcount(factory
);
5172 ok(refcount
== 2, "Get unexpected refcount %u.\n", refcount
);
5173 refcount
= get_refcount(adapter
);
5174 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5178 MONITORINFOEXW monitor_info
;
5181 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output
);
5182 if (hr
== DXGI_ERROR_NOT_FOUND
)
5184 ok(SUCCEEDED(hr
), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5186 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output2
);
5187 ok(SUCCEEDED(hr
), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5188 ok(output
!= output2
, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output
, output2
);
5189 refcount
= get_refcount(output
);
5190 ok(refcount
== 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount
, j
, i
);
5191 IDXGIOutput_Release(output2
);
5193 refcount
= get_refcount(factory
);
5194 ok(refcount
== 2, "Get unexpected refcount %u.\n", refcount
);
5195 refcount
= get_refcount(adapter
);
5196 ok(refcount
== 2, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5197 refcount
= get_refcount(output
);
5198 ok(refcount
== 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount
, j
, i
);
5200 hr
= IDXGIOutput_GetDesc(output
, &desc
);
5201 ok(SUCCEEDED(hr
), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5203 monitor_info
.cbSize
= sizeof(monitor_info
);
5204 ret
= GetMonitorInfoW(desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
5205 ok(ret
, "Failed to get monitor info.\n");
5206 ok(!lstrcmpW(desc
.DeviceName
, monitor_info
.szDevice
), "Got unexpected device name %s, expected %s.\n",
5207 wine_dbgstr_w(desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
5208 ok(EqualRect(&desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
5209 "Got unexpected desktop coordinates %s, expected %s.\n",
5210 wine_dbgstr_rect(&desc
.DesktopCoordinates
),
5211 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
5213 IDXGIOutput_Release(output
);
5214 refcount
= get_refcount(adapter
);
5215 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5218 IDXGIAdapter_Release(adapter
);
5219 refcount
= get_refcount(factory
);
5220 ok(refcount
== 1, "Get unexpected refcount %u.\n", refcount
);
5223 refcount
= IDXGIFactory_Release(factory
);
5224 ok(!refcount
, "IDXGIFactory has %u references left.\n", refcount
);
5229 IDXGIAdapter IDXGIAdapter_iface
;
5230 IDXGIAdapter
*wrapped_iface
;
5233 static inline struct dxgi_adapter
*impl_from_IDXGIAdapter(IDXGIAdapter
*iface
)
5235 return CONTAINING_RECORD(iface
, struct dxgi_adapter
, IDXGIAdapter_iface
);
5238 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryInterface(IDXGIAdapter
*iface
, REFIID iid
, void **out
)
5240 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5242 if (IsEqualGUID(iid
, &IID_IDXGIAdapter
)
5243 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5244 || IsEqualGUID(iid
, &IID_IUnknown
))
5246 IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5250 return IDXGIAdapter_QueryInterface(adapter
->wrapped_iface
, iid
, out
);
5253 static ULONG STDMETHODCALLTYPE
dxgi_adapter_AddRef(IDXGIAdapter
*iface
)
5255 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5256 return IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5259 static ULONG STDMETHODCALLTYPE
dxgi_adapter_Release(IDXGIAdapter
*iface
)
5261 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5262 return IDXGIAdapter_Release(adapter
->wrapped_iface
);
5265 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateData(IDXGIAdapter
*iface
,
5266 REFGUID guid
, UINT data_size
, const void *data
)
5268 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5269 return IDXGIAdapter_SetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5272 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateDataInterface(IDXGIAdapter
*iface
,
5273 REFGUID guid
, const IUnknown
*object
)
5275 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5276 return IDXGIAdapter_SetPrivateDataInterface(adapter
->wrapped_iface
, guid
, object
);
5279 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetPrivateData(IDXGIAdapter
*iface
,
5280 REFGUID guid
, UINT
*data_size
, void *data
)
5282 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5283 return IDXGIAdapter_GetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5286 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetParent(IDXGIAdapter
*iface
, REFIID iid
, void **parent
)
5288 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5289 return IDXGIAdapter_GetParent(adapter
->wrapped_iface
, iid
, parent
);
5292 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_EnumOutputs(IDXGIAdapter
*iface
,
5293 UINT output_idx
, IDXGIOutput
**output
)
5295 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5296 return IDXGIAdapter_EnumOutputs(adapter
->wrapped_iface
, output_idx
, output
);
5299 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc(IDXGIAdapter
*iface
, DXGI_ADAPTER_DESC
*desc
)
5301 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5302 return IDXGIAdapter_GetDesc(adapter
->wrapped_iface
, desc
);
5305 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter
*iface
,
5306 REFGUID guid
, LARGE_INTEGER
*umd_version
)
5308 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5309 return IDXGIAdapter_CheckInterfaceSupport(adapter
->wrapped_iface
, guid
, umd_version
);
5312 static const struct IDXGIAdapterVtbl dxgi_adapter_vtbl
=
5314 dxgi_adapter_QueryInterface
,
5315 dxgi_adapter_AddRef
,
5316 dxgi_adapter_Release
,
5317 dxgi_adapter_SetPrivateData
,
5318 dxgi_adapter_SetPrivateDataInterface
,
5319 dxgi_adapter_GetPrivateData
,
5320 dxgi_adapter_GetParent
,
5321 dxgi_adapter_EnumOutputs
,
5322 dxgi_adapter_GetDesc
,
5323 dxgi_adapter_CheckInterfaceSupport
,
5326 static void test_object_wrapping(void)
5328 struct dxgi_adapter wrapper
;
5329 DXGI_ADAPTER_DESC desc
;
5330 IDXGIAdapter
*adapter
;
5331 IDXGIFactory
*factory
;
5332 ID3D10Device1
*device
;
5336 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5337 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
5339 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5340 if (hr
== DXGI_ERROR_NOT_FOUND
)
5342 skip("Could not enumerate adapters.\n");
5343 IDXGIFactory_Release(factory
);
5346 ok(hr
== S_OK
, "Failed to enumerate adapter, hr %#x.\n", hr
);
5348 wrapper
.IDXGIAdapter_iface
.lpVtbl
= &dxgi_adapter_vtbl
;
5349 wrapper
.wrapped_iface
= adapter
;
5351 hr
= D3D10CreateDevice1(&wrapper
.IDXGIAdapter_iface
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
5352 0, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
);
5355 refcount
= ID3D10Device1_Release(device
);
5356 ok(!refcount
, "Device has %u references left.\n", refcount
);
5359 hr
= IDXGIAdapter_GetDesc(&wrapper
.IDXGIAdapter_iface
, &desc
);
5360 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
5362 refcount
= IDXGIAdapter_Release(&wrapper
.IDXGIAdapter_iface
);
5363 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
5364 refcount
= IDXGIFactory_Release(factory
);
5365 ok(!refcount
, "Factory has %u references left.\n", refcount
);
5374 static BOOL CALLBACK
enum_monitor_proc(HMONITOR monitor
, HDC dc
, RECT
*rect
, LPARAM lparam
)
5376 struct adapter_info
*adapter_info
= (struct adapter_info
*)lparam
;
5377 MONITORINFOEXW monitor_info
;
5379 monitor_info
.cbSize
= sizeof(monitor_info
);
5380 if (GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
)
5381 && !lstrcmpiW(adapter_info
->name
, monitor_info
.szDevice
))
5383 adapter_info
->monitor
= monitor
;
5390 static HMONITOR
get_monitor(const WCHAR
*adapter_name
)
5392 struct adapter_info info
= {adapter_name
, NULL
};
5394 EnumDisplayMonitors(NULL
, NULL
, enum_monitor_proc
, (LPARAM
)&info
);
5395 return info
.monitor
;
5398 static void test_multi_adapter(void)
5400 unsigned int output_count
= 0, expected_output_count
= 0;
5401 unsigned int adapter_index
, output_index
, device_index
;
5402 DXGI_OUTPUT_DESC old_output_desc
, output_desc
;
5403 DXGI_ADAPTER_DESC1 adapter_desc1
;
5404 DXGI_ADAPTER_DESC adapter_desc
;
5405 DISPLAY_DEVICEW display_device
;
5406 MONITORINFO monitor_info
;
5407 DEVMODEW old_mode
, mode
;
5408 IDXGIAdapter1
*adapter1
;
5409 IDXGIFactory
*factory
;
5410 IDXGIAdapter
*adapter
;
5411 IDXGIOutput
*output
;
5417 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
)))
5419 skip("Failed to create IDXGIFactory, hr %#x.\n", hr
);
5423 hr
= IDXGIFactory_EnumAdapters(factory
, 0, NULL
);
5424 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5426 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5427 if (hr
== DXGI_ERROR_NOT_FOUND
)
5429 skip("Could not enumerate adapters.\n");
5430 IDXGIFactory_Release(factory
);
5433 ok(hr
== S_OK
, "Failed to enumerate adapter, hr %#x.\n", hr
);
5435 for (adapter_index
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)); ++adapter_index
)
5437 for (output_index
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
)); ++output_index
)
5439 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5440 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5444 display_device
.cb
= sizeof(display_device
);
5445 for (device_index
= 0; EnumDisplayDevicesW(NULL
, device_index
, &display_device
, 0); ++device_index
)
5447 if (!lstrcmpiW(display_device
.DeviceName
, output_desc
.DeviceName
))
5453 ok(found
, "Adapter %u output %u: Failed to find device %s.\n",
5454 adapter_index
, output_index
, wine_dbgstr_w(output_desc
.DeviceName
));
5456 ok(display_device
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
5457 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5458 output_index
, display_device
.StateFlags
);
5459 if (!adapter_index
&& !output_index
)
5460 ok(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
,
5461 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5462 output_index
, display_device
.StateFlags
);
5464 ok(!(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
),
5465 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5466 output_index
, display_device
.StateFlags
);
5468 /* Should have the same monitor handle. */
5469 monitor
= get_monitor(display_device
.DeviceName
);
5470 ok(!!monitor
, "Adapter %u output %u: Failed to find monitor %s.\n", adapter_index
,
5471 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5472 ok(monitor
== output_desc
.Monitor
,
5473 "Adapter %u output %u: Got unexpected monitor %p, expected %p.\n",
5474 adapter_index
, output_index
, monitor
, output_desc
.Monitor
);
5476 /* Should have the same monitor rectangle. */
5477 monitor_info
.cbSize
= sizeof(monitor_info
);
5478 ok(GetMonitorInfoA(monitor
, &monitor_info
),
5479 "Adapter %u output %u: Failed to get monitor info, error %#x.\n", adapter_index
,
5480 output_index
, GetLastError());
5481 ok(EqualRect(&monitor_info
.rcMonitor
, &output_desc
.DesktopCoordinates
),
5482 "Adapter %u output %u: Got unexpected output rect %s, expected %s.\n",
5483 adapter_index
, output_index
, wine_dbgstr_rect(&monitor_info
.rcMonitor
),
5484 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5488 /* Test output description after it got detached */
5489 if (display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
)
5491 IDXGIOutput_Release(output
);
5495 old_output_desc
= output_desc
;
5497 /* Save current display settings */
5498 memset(&old_mode
, 0, sizeof(old_mode
));
5499 old_mode
.dmSize
= sizeof(old_mode
);
5500 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &old_mode
);
5501 /* Win10 TestBots may return FALSE but it's actually successful */
5502 ok(ret
|| broken(!ret
),
5503 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n",
5504 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5508 memset(&mode
, 0, sizeof(mode
));
5509 mode
.dmSize
= sizeof(mode
);
5510 mode
.dmFields
= DM_POSITION
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
5511 mode
.dmPosition
= old_mode
.dmPosition
;
5512 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &mode
, NULL
,
5513 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5514 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5515 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5516 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5517 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5518 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5519 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5520 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5522 /* Check if it is really detached */
5523 memset(&mode
, 0, sizeof(mode
));
5524 mode
.dmSize
= sizeof(mode
);
5525 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &mode
);
5526 /* Win10 TestBots may return FALSE but it's actually successful */
5527 ok(ret
|| broken(!ret
) ,
5528 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n",
5529 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5531 if (mode
.dmPelsWidth
&& mode
.dmPelsHeight
)
5533 skip("Adapter %u output %u: Failed to detach device %s.\n", adapter_index
,
5534 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5535 IDXGIOutput_Release(output
);
5539 /* Only the AttachedToDesktop field is updated after an output is detached.
5540 * IDXGIAdapter_EnumOutputs() has to be called again to get other fields updated.
5541 * But resolution changes are reflected right away. This weird behaviour is currently
5542 * unimplemented in Wine */
5543 memset(&output_desc
, 0, sizeof(output_desc
));
5544 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5545 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5547 ok(!lstrcmpiW(output_desc
.DeviceName
, old_output_desc
.DeviceName
),
5548 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5549 output_index
, wine_dbgstr_w(old_output_desc
.DeviceName
),
5550 wine_dbgstr_w(output_desc
.DeviceName
));
5552 ok(EqualRect(&output_desc
.DesktopCoordinates
, &old_output_desc
.DesktopCoordinates
),
5553 "Adapter %u output %u: Expect desktop coordinates %s, got %s.\n",
5554 adapter_index
, output_index
,
5555 wine_dbgstr_rect(&old_output_desc
.DesktopCoordinates
),
5556 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5557 ok(!output_desc
.AttachedToDesktop
,
5558 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5560 ok(output_desc
.Rotation
== old_output_desc
.Rotation
,
5561 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5562 output_index
, old_output_desc
.Rotation
, output_desc
.Rotation
);
5564 ok(output_desc
.Monitor
== old_output_desc
.Monitor
,
5565 "Adapter %u output %u: Expect monitor %p, got %p.\n", adapter_index
,
5566 output_index
, old_output_desc
.Monitor
, output_desc
.Monitor
);
5567 IDXGIOutput_Release(output
);
5569 /* Call IDXGIAdapter_EnumOutputs() again to get up-to-date output description */
5570 hr
= IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
);
5571 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5573 memset(&output_desc
, 0, sizeof(output_desc
));
5574 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5575 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5577 ok(!lstrcmpiW(output_desc
.DeviceName
, display_device
.DeviceName
),
5578 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5579 output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5580 wine_dbgstr_w(output_desc
.DeviceName
));
5581 ok(IsRectEmpty(&output_desc
.DesktopCoordinates
),
5582 "Adapter %u output %u: Expect desktop rect empty, got %s.\n", adapter_index
,
5583 output_index
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5584 ok(!output_desc
.AttachedToDesktop
,
5585 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5587 ok(output_desc
.Rotation
== DXGI_MODE_ROTATION_IDENTITY
,
5588 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5589 output_index
, DXGI_MODE_ROTATION_IDENTITY
, output_desc
.Rotation
);
5590 ok(!output_desc
.Monitor
, "Adapter %u output %u: Expect monitor NULL.\n", adapter_index
,
5593 /* Restore settings */
5594 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &old_mode
, NULL
,
5595 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5596 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5597 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5598 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5599 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5600 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5601 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5602 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5604 IDXGIOutput_Release(output
);
5607 IDXGIAdapter_Release(adapter
);
5610 /* Windows 8+ always have a WARP adapter present at the end. */
5611 todo_wine
ok(adapter_index
>= 2 || broken(adapter_index
< 2) /* Windows 7 and before */,
5612 "Got unexpected adapter count %u.\n", adapter_index
);
5613 if (adapter_index
< 2)
5615 todo_wine
win_skip("WARP adapter missing, skipping tests.\n");
5619 hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
- 1, &adapter
);
5620 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5621 hr
= IDXGIAdapter_GetDesc(adapter
, &adapter_desc
);
5622 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5623 todo_wine
ok(!lstrcmpW(adapter_desc
.Description
, L
"Microsoft Basic Render Driver"),
5624 "Got unexpected description %s.\n", wine_dbgstr_w(adapter_desc
.Description
));
5625 todo_wine
ok(adapter_desc
.VendorId
== 0x1414,
5626 "Got unexpected vendor ID %#x.\n", adapter_desc
.VendorId
);
5627 todo_wine
ok(adapter_desc
.DeviceId
== 0x008c,
5628 "Got unexpected device ID %#x.\n", adapter_desc
.DeviceId
);
5629 ok(adapter_desc
.SubSysId
== 0x0000,
5630 "Got unexpected sub-system ID %#x.\n", adapter_desc
.SubSysId
);
5631 ok(adapter_desc
.Revision
== 0x0000,
5632 "Got unexpected revision %#x.\n", adapter_desc
.Revision
);
5633 todo_wine
ok(!adapter_desc
.DedicatedVideoMemory
,
5634 "Got unexpected DedicatedVideoMemory %#lx.\n", adapter_desc
.DedicatedVideoMemory
);
5635 ok(!adapter_desc
.DedicatedSystemMemory
,
5636 "Got unexpected DedicatedSystemMemory %#lx.\n", adapter_desc
.DedicatedSystemMemory
);
5638 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
5639 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#x.\n", hr
);
5642 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &adapter_desc1
);
5643 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5644 todo_wine
ok(adapter_desc1
.Flags
== DXGI_ADAPTER_FLAG_SOFTWARE
,
5645 "Got unexpected flags %#x.\n", adapter_desc1
.Flags
);
5646 IDXGIAdapter1_Release(adapter1
);
5649 IDXGIAdapter_Release(adapter
);
5652 IDXGIFactory_Release(factory
);
5654 expected_output_count
= GetSystemMetrics(SM_CMONITORS
);
5655 todo_wine_if(expected_output_count
> 1)
5656 ok(output_count
== expected_output_count
, "Expect output count %d, got %d\n",
5657 expected_output_count
, output_count
);
5662 unsigned int message
;
5664 WPARAM expect_wparam
;
5667 static BOOL expect_no_messages
;
5668 static const struct message
*expect_messages
;
5669 static const struct message
*expect_messages_broken
;
5671 static BOOL
check_message(const struct message
*expected
,
5672 HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5674 if (expected
->message
!= message
)
5677 if (expected
->check_wparam
)
5679 ok(wparam
== expected
->expect_wparam
,
5680 "Got unexpected wparam %lx for message %x, expected %lx.\n",
5681 wparam
, message
, expected
->expect_wparam
);
5687 static LRESULT CALLBACK
test_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5689 ok(!expect_no_messages
, "Got unexpected message %#x, hwnd %p, wparam %#lx, lparam %#lx.\n",
5690 message
, hwnd
, wparam
, lparam
);
5692 if (expect_messages
)
5694 if (check_message(expect_messages
, hwnd
, message
, wparam
, lparam
))
5698 if (expect_messages_broken
)
5700 if (check_message(expect_messages_broken
, hwnd
, message
, wparam
, lparam
))
5701 ++expect_messages_broken
;
5704 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
5707 static void test_swapchain_window_messages(void)
5709 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5710 IDXGISwapChain
*swapchain
;
5711 DXGI_MODE_DESC mode_desc
;
5712 IDXGIFactory
*factory
;
5713 IDXGIAdapter
*adapter
;
5714 IDXGIDevice
*device
;
5720 static const struct message enter_fullscreen_messages
[] =
5722 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5723 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5724 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5725 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5726 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5727 {WM_GETMINMAXINFO
, FALSE
, 0},
5728 {WM_NCCALCSIZE
, FALSE
, 0},
5729 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5730 {WM_MOVE
, FALSE
, 0},
5731 {WM_SIZE
, FALSE
, 0},
5734 static const struct message enter_fullscreen_messages_vista
[] =
5736 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5737 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5738 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5739 {WM_NCCALCSIZE
, FALSE
, 0},
5740 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5741 {WM_MOVE
, FALSE
, 0},
5742 {WM_SIZE
, FALSE
, 0},
5743 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5744 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5745 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5746 {WM_GETMINMAXINFO
, FALSE
, 0},
5747 {WM_NCCALCSIZE
, FALSE
, 0},
5748 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5749 {WM_SIZE
, FALSE
, 0},
5752 static const struct message leave_fullscreen_messages
[] =
5754 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5755 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5756 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5757 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5758 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5759 {WM_GETMINMAXINFO
, FALSE
, 0},
5760 {WM_NCCALCSIZE
, FALSE
, 0},
5761 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5762 {WM_MOVE
, FALSE
, 0},
5763 {WM_SIZE
, FALSE
, 0},
5766 static const struct message resize_target_messages
[] =
5768 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5769 {WM_GETMINMAXINFO
, FALSE
, 0},
5770 {WM_NCCALCSIZE
, FALSE
, 0},
5771 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5772 {WM_SIZE
, FALSE
, 0},
5776 if (!(device
= create_device(0)))
5778 skip("Failed to create device.\n");
5782 memset(&wc
, 0, sizeof(wc
));
5783 wc
.lpfnWndProc
= test_wndproc
;
5784 wc
.lpszClassName
= "dxgi_test_wndproc_wc";
5785 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
5786 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
5787 ok(!!window
, "Failed to create window.\n");
5789 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
5790 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
5791 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
5792 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
5793 IDXGIAdapter_Release(adapter
);
5795 swapchain_desc
.BufferDesc
.Width
= 800;
5796 swapchain_desc
.BufferDesc
.Height
= 600;
5797 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5798 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5799 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
5800 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5801 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5802 swapchain_desc
.SampleDesc
.Count
= 1;
5803 swapchain_desc
.SampleDesc
.Quality
= 0;
5804 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5805 swapchain_desc
.BufferCount
= 1;
5806 swapchain_desc
.OutputWindow
= window
;
5807 swapchain_desc
.Windowed
= TRUE
;
5808 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
5809 swapchain_desc
.Flags
= 0;
5811 /* create swapchain */
5813 expect_no_messages
= TRUE
;
5814 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
5815 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
5817 expect_no_messages
= FALSE
;
5820 expect_messages
= resize_target_messages
;
5821 memset(&mode_desc
, 0, sizeof(mode_desc
));
5822 mode_desc
.Width
= 800;
5823 mode_desc
.Height
= 600;
5824 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5825 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
5827 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5829 expect_messages
= resize_target_messages
;
5830 memset(&mode_desc
, 0, sizeof(mode_desc
));
5831 mode_desc
.Width
= 400;
5832 mode_desc
.Height
= 200;
5833 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5834 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
5836 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5838 /* enter fullscreen */
5839 expect_messages
= enter_fullscreen_messages
;
5840 expect_messages_broken
= enter_fullscreen_messages_vista
;
5841 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
5842 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
5843 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
5844 "Failed to enter fullscreen, hr %#x.\n", hr
);
5847 skip("Could not change fullscreen state.\n");
5852 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
5853 "Expected message %#x or %#x.\n",
5854 expect_messages
->message
, expect_messages_broken
->message
);
5855 expect_messages_broken
= NULL
;
5857 /* leave fullscreen */
5858 expect_messages
= leave_fullscreen_messages
;
5859 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
5860 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5862 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5863 expect_messages
= NULL
;
5865 refcount
= IDXGISwapChain_Release(swapchain
);
5866 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
5868 /* create fullscreen swapchain */
5869 DestroyWindow(window
);
5870 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
5871 ok(!!window
, "Failed to create window.\n");
5872 swapchain_desc
.OutputWindow
= window
;
5873 swapchain_desc
.Windowed
= FALSE
;
5874 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
5877 expect_messages
= enter_fullscreen_messages
;
5878 expect_messages_broken
= enter_fullscreen_messages_vista
;
5879 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
5880 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
5883 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
5884 "Expected message %#x or %#x.\n",
5885 expect_messages
->message
, expect_messages_broken
->message
);
5886 expect_messages_broken
= NULL
;
5888 /* leave fullscreen */
5889 expect_messages
= leave_fullscreen_messages
;
5890 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
5891 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5893 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5894 expect_messages
= NULL
;
5897 refcount
= IDXGISwapChain_Release(swapchain
);
5898 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
5899 DestroyWindow(window
);
5901 refcount
= IDXGIDevice_Release(device
);
5902 ok(!refcount
, "Device has %u references left.\n", refcount
);
5903 refcount
= IDXGIFactory_Release(factory
);
5904 ok(!refcount
, "Factory has %u references left.\n", refcount
);
5906 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
5909 static void test_swapchain_window_styles(void)
5911 LONG style
, exstyle
, fullscreen_style
, fullscreen_exstyle
;
5912 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5913 IDXGISwapChain
*swapchain
;
5914 IDXGIFactory
*factory
;
5915 IDXGIAdapter
*adapter
;
5916 IDXGIDevice
*device
;
5923 LONG style
, exstyle
;
5924 LONG expected_style
, expected_exstyle
;
5928 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
, 0,
5929 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
,
5931 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
, 0,
5932 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
| WS_VISIBLE
,
5934 {WS_OVERLAPPED
| WS_VISIBLE
, 0,
5935 WS_OVERLAPPED
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
5936 {WS_OVERLAPPED
| WS_MAXIMIZE
, 0,
5937 WS_OVERLAPPED
| WS_MAXIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
5938 {WS_OVERLAPPED
| WS_MINIMIZE
, 0,
5939 WS_OVERLAPPED
| WS_MINIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
5940 {WS_CAPTION
| WS_DISABLED
, WS_EX_TOPMOST
,
5941 WS_CAPTION
| WS_DISABLED
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
5942 {WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
, WS_EX_TOPMOST
,
5943 WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
5944 {WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, WS_EX_APPWINDOW
,
5945 WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
},
5946 {WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
5947 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
5949 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
5950 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
5954 if (!(device
= create_device(0)))
5956 skip("Failed to create device.\n");
5960 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
5961 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
5962 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
5963 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
5964 IDXGIAdapter_Release(adapter
);
5966 swapchain_desc
.BufferDesc
.Width
= 800;
5967 swapchain_desc
.BufferDesc
.Height
= 600;
5968 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5969 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5970 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
5971 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5972 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5973 swapchain_desc
.SampleDesc
.Count
= 1;
5974 swapchain_desc
.SampleDesc
.Quality
= 0;
5975 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5976 swapchain_desc
.BufferCount
= 1;
5977 swapchain_desc
.Windowed
= TRUE
;
5978 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
5979 swapchain_desc
.Flags
= 0;
5981 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
5983 swapchain_desc
.OutputWindow
= CreateWindowExA(tests
[i
].exstyle
, "static", "dxgi_test",
5984 tests
[i
].style
, 0, 0, 400, 200, 0, 0, 0, 0);
5986 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
5987 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
5988 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
5989 i
, style
, tests
[i
].expected_style
);
5990 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
5991 i
, exstyle
, tests
[i
].expected_exstyle
);
5993 fullscreen_style
= tests
[i
].expected_style
& ~(WS_POPUP
| WS_MAXIMIZEBOX
5994 | WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_SYSMENU
| WS_DLGFRAME
| WS_BORDER
);
5995 fullscreen_exstyle
= tests
[i
].expected_exstyle
& ~(WS_EX_DLGMODALFRAME
5996 | WS_EX_TOOLWINDOW
| WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_CONTEXTHELP
);
5997 fullscreen_exstyle
|= WS_EX_TOPMOST
;
5999 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6000 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
6002 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6003 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6004 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6005 i
, style
, tests
[i
].expected_style
);
6006 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6007 i
, exstyle
, tests
[i
].expected_exstyle
);
6009 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6010 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6011 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6012 "Failed to set fullscreen state, hr %#x.\n", hr
);
6015 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6016 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6018 ok(style
== fullscreen_style
, "Test %u: Got style %#x, expected %#x.\n",
6019 i
, style
, fullscreen_style
);
6020 ok(exstyle
== fullscreen_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6021 i
, exstyle
, fullscreen_exstyle
);
6023 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6024 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6028 skip("Test %u: Could not change fullscreen state.\n", i
);
6031 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6032 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6033 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6034 i
, style
, tests
[i
].expected_style
);
6035 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6036 i
, exstyle
, tests
[i
].expected_exstyle
);
6038 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6039 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6040 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6041 "Failed to set fullscreen state, hr %#x.\n", hr
);
6044 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6045 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6047 ok(style
== fullscreen_style
, "Test %u: Got style %#x, expected %#x.\n",
6048 i
, style
, fullscreen_style
);
6049 ok(exstyle
== fullscreen_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6050 i
, exstyle
, fullscreen_exstyle
);
6052 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_STYLE
, fullscreen_style
);
6053 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
, fullscreen_exstyle
);
6055 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6056 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6058 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6059 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6061 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6062 i
, style
, tests
[i
].expected_style
);
6064 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6065 i
, exstyle
, tests
[i
].expected_exstyle
);
6069 skip("Test %u: Could not change fullscreen state.\n", i
);
6072 refcount
= IDXGISwapChain_Release(swapchain
);
6073 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6075 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6076 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6078 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6079 i
, style
, tests
[i
].expected_style
);
6081 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6082 i
, exstyle
, tests
[i
].expected_exstyle
);
6084 DestroyWindow(swapchain_desc
.OutputWindow
);
6087 refcount
= IDXGIDevice_Release(device
);
6088 ok(!refcount
, "Device has %u references left.\n", refcount
);
6089 refcount
= IDXGIFactory_Release(factory
);
6090 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6093 static void test_gamma_control(void)
6095 DXGI_GAMMA_CONTROL_CAPABILITIES caps
;
6096 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6097 IDXGISwapChain
*swapchain
;
6098 DXGI_GAMMA_CONTROL gamma
;
6099 IDXGIFactory
*factory
;
6100 IDXGIAdapter
*adapter
;
6101 IDXGIDevice
*device
;
6102 IDXGIOutput
*output
;
6107 if (!(device
= create_device(0)))
6109 skip("Failed to create device.\n");
6113 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6114 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6116 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6117 if (hr
== DXGI_ERROR_NOT_FOUND
)
6119 skip("Adapter doesn't have any outputs.\n");
6120 IDXGIAdapter_Release(adapter
);
6121 IDXGIDevice_Release(device
);
6124 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6126 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6128 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6129 IDXGIOutput_Release(output
);
6131 swapchain_desc
.BufferDesc
.Width
= 640;
6132 swapchain_desc
.BufferDesc
.Height
= 480;
6133 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6134 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6135 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6136 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6137 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6138 swapchain_desc
.SampleDesc
.Count
= 1;
6139 swapchain_desc
.SampleDesc
.Quality
= 0;
6140 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6141 swapchain_desc
.BufferCount
= 1;
6142 swapchain_desc
.OutputWindow
= create_window();
6143 swapchain_desc
.Windowed
= TRUE
;
6144 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6145 swapchain_desc
.Flags
= 0;
6147 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6148 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6150 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6151 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
6152 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6153 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6154 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6155 "Failed to enter fullscreen, hr %#x.\n", hr
);
6158 skip("Could not change fullscreen state.\n");
6162 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
6163 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6165 memset(&caps
, 0, sizeof(caps
));
6166 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6167 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6169 ok(caps
.MaxConvertedValue
> caps
.MinConvertedValue
6170 || broken(caps
.MaxConvertedValue
== 0.0f
&& caps
.MinConvertedValue
== 1.0f
) /* WARP */,
6171 "Expected max gamma value (%.8e) to be bigger than min value (%.8e).\n",
6172 caps
.MaxConvertedValue
, caps
.MinConvertedValue
);
6174 for (i
= 1; i
< caps
.NumGammaControlPoints
; ++i
)
6176 ok(caps
.ControlPointPositions
[i
] > caps
.ControlPointPositions
[i
- 1],
6177 "Expected control point positions to be strictly monotonically increasing (%.8e > %.8e).\n",
6178 caps
.ControlPointPositions
[i
], caps
.ControlPointPositions
[i
- 1]);
6181 memset(&gamma
, 0, sizeof(gamma
));
6182 hr
= IDXGIOutput_GetGammaControl(output
, &gamma
);
6184 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6185 hr
= IDXGIOutput_SetGammaControl(output
, &gamma
);
6186 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6188 IDXGIOutput_Release(output
);
6190 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6191 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6194 refcount
= IDXGISwapChain_Release(swapchain
);
6195 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6196 DestroyWindow(swapchain_desc
.OutputWindow
);
6198 IDXGIAdapter_Release(adapter
);
6199 refcount
= IDXGIDevice_Release(device
);
6200 ok(!refcount
, "Device has %u references left.\n", refcount
);
6201 refcount
= IDXGIFactory_Release(factory
);
6202 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6205 static void test_window_association(IUnknown
*device
, BOOL is_d3d12
)
6207 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6208 LONG_PTR original_wndproc
, wndproc
;
6209 IDXGIFactory
*factory
, *factory2
;
6210 IDXGISwapChain
*swapchain
;
6211 IDXGIOutput
*output
;
6221 BOOL expect_fullscreen
;
6226 /* There are two reasons why VK_TAB and VK_ESC are not tested here:
6228 * - Posting them to the window doesn't exit fullscreen like
6229 * Alt+Enter does. Alt+Tab and Alt+Esc are handled somewhere else.
6230 * E.g., not calling IDXGISwapChain::Present() will break Alt+Tab
6231 * and Alt+Esc while Alt+Enter will still function.
6233 * - Posting them hangs the posting thread. Another thread that keeps
6234 * sending input is needed to avoid the hang. The hang is not
6235 * because of flush_events(). */
6238 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6239 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6240 {DXGI_MWA_NO_ALT_ENTER
, FALSE
, TRUE
},
6241 {DXGI_MWA_NO_ALT_ENTER
, FALSE
},
6242 {DXGI_MWA_NO_PRINT_SCREEN
, TRUE
},
6243 {DXGI_MWA_NO_PRINT_SCREEN
, FALSE
},
6248 swapchain_desc
.BufferDesc
.Width
= 640;
6249 swapchain_desc
.BufferDesc
.Height
= 480;
6250 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6251 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6252 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6253 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6254 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6255 swapchain_desc
.SampleDesc
.Count
= 1;
6256 swapchain_desc
.SampleDesc
.Quality
= 0;
6257 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6258 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6259 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6260 swapchain_desc
.Windowed
= TRUE
;
6261 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6262 swapchain_desc
.Flags
= 0;
6264 original_wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6266 hwnd2
= CreateWindowA("static", "dxgi_test2", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6267 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory2
);
6268 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
6270 get_factory(device
, is_d3d12
, &factory
);
6272 hr
= IDXGIFactory_GetWindowAssociation(factory
, NULL
);
6273 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6275 for (i
= 0; i
<= DXGI_MWA_VALID
; ++i
)
6277 hr
= IDXGIFactory_MakeWindowAssociation(factory
, NULL
, i
);
6278 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6280 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, i
);
6281 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6283 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6284 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#lx, expected %#lx for flags %#x.\n",
6285 wndproc
, original_wndproc
, i
);
6287 hwnd
= (HWND
)0xdeadbeef;
6288 hr
= IDXGIFactory_GetWindowAssociation(factory
, &hwnd
);
6289 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6290 /* Apparently GetWindowAssociation() always returns NULL, even when
6291 * MakeWindowAssociation() and GetWindowAssociation() are both
6292 * successfully called. */
6293 ok(!hwnd
, "Expect null associated window.\n");
6296 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, DXGI_MWA_VALID
+ 1);
6297 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6299 /* Alt+Enter tests. */
6300 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6301 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6303 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6304 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#lx, expected %#lx.\n", wndproc
, original_wndproc
);
6306 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6307 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6308 || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Windows 7 testbot */,
6309 "Got unexpected hr %#x.\n", hr
);
6312 skip("Could not change fullscreen state.\n");
6316 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6317 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6319 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6321 /* First associate a window with the opposite flags. */
6322 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6323 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6325 /* Associate the current test window. */
6326 hwnd
= tests
[i
].flag
? swapchain_desc
.OutputWindow
: NULL
;
6327 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd
, tests
[i
].flag
);
6328 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6330 /* Associating a new test window doesn't override the old window. */
6331 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6332 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6334 /* Associations with a different factory don't affect the existing
6336 hr
= IDXGIFactory_MakeWindowAssociation(factory2
, hwnd
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6337 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6339 /* Post synthesized Alt + VK_RETURN WM_SYSKEYDOWN. */
6340 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
6341 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
6344 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
6345 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6346 ok(fullscreen
== tests
[i
].expect_fullscreen
6347 || broken(tests
[i
].broken_d3d10
&& fullscreen
),
6348 "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
6349 ok(fullscreen
? !!output
: !output
, "Test %u: Got wrong output.\n", i
);
6351 IDXGIOutput_Release(output
);
6353 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6354 ok(wndproc
== original_wndproc
, "Test %u: Got unexpected wndproc %#lx, expected %#lx.\n",
6355 i
, wndproc
, original_wndproc
);
6359 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6360 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6362 refcount
= IDXGIFactory_Release(factory2
);
6363 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6364 DestroyWindow(hwnd2
);
6366 refcount
= IDXGISwapChain_Release(swapchain
);
6367 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6368 DestroyWindow(swapchain_desc
.OutputWindow
);
6370 refcount
= IDXGIFactory_Release(factory
);
6371 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
6374 static void test_output_ownership(IUnknown
*device
, BOOL is_d3d12
)
6376 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc
;
6377 D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_ownership_desc
;
6378 D3DKMT_CLOSEADAPTER close_adapter_desc
;
6379 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6380 DXGI_OUTPUT_DESC output_desc
;
6381 IDXGISwapChain
*swapchain
;
6382 IDXGIFactory
*factory
;
6383 IDXGIAdapter
*adapter
;
6384 IDXGIOutput
*output
;
6390 if (!pD3DKMTCheckVidPnExclusiveOwnership
6391 || pD3DKMTCheckVidPnExclusiveOwnership(NULL
) == STATUS_PROCEDURE_NOT_FOUND
)
6393 win_skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n");
6397 get_factory(device
, is_d3d12
, &factory
);
6398 adapter
= get_adapter(device
, is_d3d12
);
6401 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
6402 IDXGIFactory_Release(factory
);
6406 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6407 IDXGIAdapter_Release(adapter
);
6408 if (hr
== DXGI_ERROR_NOT_FOUND
)
6410 skip("Adapter doesn't have any outputs.\n");
6411 IDXGIFactory_Release(factory
);
6414 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6416 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6417 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6419 lstrcpyW(open_adapter_gdi_desc
.DeviceName
, output_desc
.DeviceName
);
6420 status
= pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc
);
6421 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
6423 check_ownership_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6424 check_ownership_desc
.VidPnSourceId
= open_adapter_gdi_desc
.VidPnSourceId
;
6425 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6426 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6429 swapchain_desc
.BufferDesc
.Width
= 800;
6430 swapchain_desc
.BufferDesc
.Height
= 600;
6431 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6432 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6433 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6434 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6435 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6436 swapchain_desc
.SampleDesc
.Count
= 1;
6437 swapchain_desc
.SampleDesc
.Quality
= 0;
6438 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6439 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6440 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
6441 swapchain_desc
.Windowed
= TRUE
;
6442 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6443 swapchain_desc
.Flags
= 0;
6444 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6445 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6447 /* Swapchain in fullscreen mode. */
6448 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
6449 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
6450 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
6451 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
6453 skip("Failed to change fullscreen state.\n");
6456 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6458 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6459 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6460 ok(fullscreen
, "Got unexpected fullscreen state.\n");
6461 /* Win10 1909 doesn't seem to grab output exclusive ownership.
6462 * And all output ownership calls return S_OK on D3D10 and D3D12 with 1909. */
6465 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6466 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6471 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6472 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6473 todo_wine
ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6474 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6475 "Got unexpected status %#x, expected %#x.\n", status
,
6476 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6478 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, FALSE
);
6479 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6480 "Got unexpected hr %#x.\n", hr
);
6481 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, TRUE
);
6482 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6483 "Got unexpected hr %#x.\n", hr
);
6484 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6486 todo_wine
ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6488 todo_wine
ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
), /* Win10 1909 */
6489 "Got unexpected hr %#x.\n", hr
);
6490 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6491 ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6492 IDXGIOutput_ReleaseOwnership(output
);
6493 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6494 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6497 /* IDXGIOutput_TakeOwnership always returns E_NOINTERFACE for d3d12. Tests
6502 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6503 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6504 "Got unexpected hr %#x.\n", hr
);
6505 IDXGIOutput_ReleaseOwnership(output
);
6507 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6508 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6509 /* Note that the "exclusive" parameter to IDXGIOutput_TakeOwnership()
6510 * seems to behave opposite to what's described by MSDN. */
6511 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6512 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6513 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6514 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6515 "Got unexpected status %#x, expected %#x.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6516 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6517 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Win10 1909 */, "Got unexpected hr %#x.\n", hr
);
6518 IDXGIOutput_ReleaseOwnership(output
);
6520 /* Swapchain in windowed mode. */
6521 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6522 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6524 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6525 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6526 ok(!fullscreen
, "Unexpected fullscreen state.\n");
6527 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6528 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6531 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6532 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6533 "Got unexpected hr %#x.\n", hr
);
6535 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6536 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6537 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6538 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6539 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
|| broken(hr
== S_OK
), /* Win10 1909 */
6540 "Got unexpected status %#x, expected %#x.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6541 IDXGIOutput_ReleaseOwnership(output
);
6542 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6543 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6547 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6548 wait_device_idle(device
);
6550 IDXGIOutput_Release(output
);
6551 IDXGISwapChain_Release(swapchain
);
6552 DestroyWindow(swapchain_desc
.OutputWindow
);
6553 refcount
= IDXGIFactory_Release(factory
);
6554 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
6556 close_adapter_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6557 status
= pD3DKMTCloseAdapter(&close_adapter_desc
);
6558 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
6561 static void test_cursor_clipping(IUnknown
*device
, BOOL is_d3d12
)
6563 unsigned int adapter_idx
, output_idx
, mode_idx
, mode_count
;
6564 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6565 DXGI_OUTPUT_DESC output_desc
;
6566 IDXGIAdapter
*adapter
= NULL
;
6567 RECT virtual_rect
, clip_rect
;
6568 unsigned int width
, height
;
6569 IDXGISwapChain
*swapchain
;
6570 DXGI_MODE_DESC
*modes
;
6571 IDXGIFactory
*factory
;
6572 IDXGIOutput
*output
;
6576 get_factory(device
, is_d3d12
, &factory
);
6578 swapchain_desc
.SampleDesc
.Count
= 1;
6579 swapchain_desc
.SampleDesc
.Quality
= 0;
6580 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6581 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6582 swapchain_desc
.Windowed
= TRUE
;
6583 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6584 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6586 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
6589 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
6592 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
,
6594 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 TestBots */
6595 "Adapter %u output %u: GetDisplayModeList failed, hr %#x.\n", adapter_idx
,
6597 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
6599 win_skip("Adapter %u output %u: GetDisplayModeList() not supported.\n", adapter_idx
,
6601 IDXGIOutput_Release(output
);
6605 modes
= heap_calloc(mode_count
, sizeof(*modes
));
6606 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
,
6608 ok(hr
== S_OK
, "Adapter %u output %u: GetDisplayModeList failed, hr %#x.\n",
6609 adapter_idx
, output_idx
, hr
);
6611 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6612 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
6614 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
6615 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
6616 for (mode_idx
= 0; mode_idx
< mode_count
; ++mode_idx
)
6618 if (modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
)
6621 ok(modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
,
6622 "Adapter %u output %u: Failed to find a different mode than %ux%u.\n",
6623 adapter_idx
, output_idx
, width
, height
);
6625 ok(ClipCursor(NULL
), "Adapter %u output %u: ClipCursor failed, error %#x.\n",
6626 adapter_idx
, output_idx
, GetLastError());
6627 get_virtual_rect(&virtual_rect
);
6628 ok(GetClipCursor(&clip_rect
),
6629 "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6630 output_idx
, GetLastError());
6631 ok(EqualRect(&clip_rect
, &virtual_rect
),
6632 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6633 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6635 swapchain_desc
.BufferDesc
.Width
= modes
[mode_idx
].Width
;
6636 swapchain_desc
.BufferDesc
.Height
= modes
[mode_idx
].Height
;
6637 swapchain_desc
.BufferDesc
.RefreshRate
= modes
[mode_idx
].RefreshRate
;
6638 swapchain_desc
.BufferDesc
.Format
= modes
[mode_idx
].Format
;
6639 swapchain_desc
.BufferDesc
.ScanlineOrdering
= modes
[mode_idx
].ScanlineOrdering
;
6640 swapchain_desc
.BufferDesc
.Scaling
= modes
[mode_idx
].Scaling
;
6641 swapchain_desc
.OutputWindow
= create_window();
6643 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
,
6645 ok(hr
== S_OK
, "Adapter %u output %u: CreateSwapChain failed, hr %#x.\n",
6646 adapter_idx
, output_idx
, hr
);
6649 get_virtual_rect(&virtual_rect
);
6650 ok(GetClipCursor(&clip_rect
),
6651 "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6652 output_idx
, GetLastError());
6653 ok(EqualRect(&clip_rect
, &virtual_rect
),
6654 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6655 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6657 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6658 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
||
6659 broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6660 "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n", adapter_idx
,
6664 skip("Adapter %u output %u: Could not change fullscreen state, hr %#x.\n",
6665 adapter_idx
, output_idx
, hr
);
6666 IDXGISwapChain_Release(swapchain
);
6667 IDXGIOutput_Release(output
);
6668 DestroyWindow(swapchain_desc
.OutputWindow
);
6673 get_virtual_rect(&virtual_rect
);
6674 ok(GetClipCursor(&clip_rect
),
6675 "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6676 output_idx
, GetLastError());
6677 ok(EqualRect(&clip_rect
, &virtual_rect
),
6678 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6679 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6681 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6682 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_idx
,
6684 refcount
= IDXGISwapChain_Release(swapchain
);
6685 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
6686 adapter_idx
, output_idx
, refcount
);
6687 refcount
= IDXGIOutput_Release(output
);
6688 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
6689 adapter_idx
, output_idx
, refcount
);
6690 DestroyWindow(swapchain_desc
.OutputWindow
);
6693 get_virtual_rect(&virtual_rect
);
6694 ok(GetClipCursor(&clip_rect
),
6695 "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6696 output_idx
, GetLastError());
6697 ok(EqualRect(&clip_rect
, &virtual_rect
),
6698 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6699 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6702 IDXGIAdapter_Release(adapter
);
6705 refcount
= IDXGIFactory_Release(factory
);
6706 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
6709 static void test_factory_check_feature_support(void)
6711 IDXGIFactory5
*factory
;
6716 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory5
, (void**)&factory
)))
6718 win_skip("IDXGIFactory5 is not available.\n");
6722 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, 0x12345678, (void *)&data
, sizeof(data
));
6723 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6725 /* Crashes on Windows. */
6728 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, NULL
, sizeof(data
));
6729 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6732 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) - 1);
6733 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6735 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) + 1);
6736 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6738 data
= (BOOL
)0xdeadbeef;
6739 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
));
6740 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6741 ok(data
== TRUE
|| data
== FALSE
, "Got unexpected data %#x.\n", data
);
6743 ref_count
= IDXGIFactory5_Release(factory
);
6744 ok(!ref_count
, "Factory has %u references left.\n", ref_count
);
6747 static void test_frame_latency_event(IUnknown
*device
, BOOL is_d3d12
)
6749 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
6750 IDXGISwapChain2
*swapchain2
;
6751 IDXGISwapChain1
*swapchain1
;
6752 IDXGIFactory2
*factory2
;
6753 IDXGIFactory
*factory
;
6762 get_factory(device
, is_d3d12
, &factory
);
6764 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
6765 IDXGIFactory_Release(factory
);
6768 win_skip("IDXGIFactory2 not available.\n");
6772 window
= create_window();
6774 swapchain_desc
.Width
= 640;
6775 swapchain_desc
.Height
= 480;
6776 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6777 swapchain_desc
.Stereo
= FALSE
;
6778 swapchain_desc
.SampleDesc
.Count
= 1;
6779 swapchain_desc
.SampleDesc
.Quality
= 0;
6780 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6781 swapchain_desc
.BufferCount
= 2;
6782 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
6783 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
6784 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
6785 swapchain_desc
.Flags
= 0;
6787 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6788 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6789 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6791 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6792 IDXGISwapChain1_Release(swapchain1
);
6795 win_skip("IDXGISwapChain2 not available.\n");
6796 IDXGIFactory2_Release(factory2
);
6797 DestroyWindow(window
);
6801 /* test swap chain without waitable object */
6802 frame_latency
= 0xdeadbeef;
6803 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6804 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6805 ok(frame_latency
== 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency
);
6806 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 1);
6807 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6808 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6809 ok(!event
, "Got unexpected event %p.\n", event
);
6811 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6812 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
6814 /* test swap chain with waitable object */
6815 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
;
6817 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6818 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6819 ok(hr
== S_OK
, "Failed to create swap chain, hr %#x.\n", hr
);
6820 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6821 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6822 IDXGISwapChain1_Release(swapchain1
);
6824 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6825 ok(!!event
, "Got unexpected event %p.\n", event
);
6827 /* auto-reset event */
6828 wait_result
= WaitForSingleObject(event
, 0);
6829 ok(!wait_result
, "Got unexpected wait result %#x.\n", wait_result
);
6830 wait_result
= WaitForSingleObject(event
, 0);
6831 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#x.\n", wait_result
);
6833 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6834 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6835 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6837 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 0);
6838 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6839 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6840 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6841 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6843 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 2);
6844 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6845 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6846 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6847 ok(frame_latency
== 2, "Got unexpected frame latency %#x.\n", frame_latency
);
6849 for (i
= 0; i
< 5; i
++)
6851 hr
= IDXGISwapChain2_Present(swapchain2
, 0, 0);
6852 ok(hr
== S_OK
, "Present %u failed with hr %#x.\n", i
, hr
);
6855 wait_result
= WaitForSingleObject(event
, 1000);
6856 ok(!wait_result
, "Got unexpected wait result %#x.\n", wait_result
);
6858 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6859 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
6860 DestroyWindow(window
);
6861 ref_count
= IDXGIFactory2_Release(factory2
);
6862 ok(ref_count
== !is_d3d12
, "Factory has %u references left.\n", ref_count
);
6865 static void test_colour_space_support(IUnknown
*device
, BOOL is_d3d12
)
6867 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
6868 IDXGISwapChain3
*swapchain3
;
6869 IDXGISwapChain1
*swapchain1
;
6870 IDXGIFactory2
*factory2
;
6871 IDXGIFactory
*factory
;
6878 static const DXGI_COLOR_SPACE_TYPE colour_spaces
[] =
6880 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
,
6881 DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
,
6882 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
,
6883 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
,
6884 DXGI_COLOR_SPACE_RESERVED
,
6885 DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
,
6886 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
,
6887 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
,
6888 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
,
6889 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
,
6890 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
,
6891 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
,
6892 DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
,
6893 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
,
6894 DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
,
6895 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
,
6896 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
,
6897 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
,
6898 DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
,
6899 DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
,
6902 get_factory(device
, is_d3d12
, &factory
);
6904 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
6905 IDXGIFactory_Release(factory
);
6908 win_skip("IDXGIFactory2 not available.\n");
6912 window
= create_window();
6914 swapchain_desc
.Width
= 640;
6915 swapchain_desc
.Height
= 480;
6916 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6917 swapchain_desc
.Stereo
= FALSE
;
6918 swapchain_desc
.SampleDesc
.Count
= 1;
6919 swapchain_desc
.SampleDesc
.Quality
= 0;
6920 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6921 swapchain_desc
.BufferCount
= 2;
6922 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
6923 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
6924 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
6925 swapchain_desc
.Flags
= 0;
6927 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6928 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6929 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6931 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain3
, (void**)&swapchain3
);
6932 IDXGISwapChain1_Release(swapchain1
);
6935 win_skip("IDXGISwapChain3 not available.\n");
6936 IDXGIFactory2_Release(factory2
);
6937 DestroyWindow(window
);
6941 for (i
= 0; i
< ARRAY_SIZE(colour_spaces
); ++i
)
6943 support
= 0xdeadbeef;
6944 hr
= IDXGISwapChain3_CheckColorSpaceSupport(swapchain3
, colour_spaces
[i
], &support
);
6945 ok(hr
== S_OK
, "Got unexpected hr %#x for test %u.\n", hr
, i
);
6946 ok(!(support
& ~DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
),
6947 "Got unexpected support flags %#x for test %u.\n", support
, i
);
6949 if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
)
6951 ok(support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
,
6952 "Required colour space not supported for test %u.\n", i
);
6954 else if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RESERVED
)
6956 ok(!support
, "Invalid colour space supported for test %u.\n", i
);
6959 hr
= IDXGISwapChain3_SetColorSpace1(swapchain3
, colour_spaces
[i
]);
6960 ok(hr
== (support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
) ? S_OK
: E_INVALIDARG
,
6961 "Got unexpected hr %#x for text %u.\n", hr
, i
);
6964 ref_count
= IDXGISwapChain3_Release(swapchain3
);
6965 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
6966 DestroyWindow(window
);
6967 ref_count
= IDXGIFactory2_Release(factory2
);
6968 ok(ref_count
== !is_d3d12
, "Factory has %u references left.\n", ref_count
);
6971 static void test_mode_change(IUnknown
*device
, BOOL is_d3d12
)
6973 unsigned int user32_width
= 0, user32_height
= 0, d3d_width
= 0, d3d_height
= 0;
6974 unsigned int display_count
= 0, mode_idx
= 0, adapter_idx
, output_idx
;
6975 DEVMODEW
*original_modes
= NULL
, old_devmode
, devmode
, devmode2
;
6976 DXGI_SWAP_CHAIN_DESC swapchain_desc
, swapchain_desc2
;
6977 IDXGIOutput
*output
, *second_output
= NULL
;
6978 WCHAR second_monitor_name
[CCHDEVICENAME
];
6979 IDXGISwapChain
*swapchain
, *swapchain2
;
6980 DXGI_OUTPUT_DESC output_desc
;
6981 IDXGIAdapter
*adapter
;
6982 IDXGIFactory
*factory
;
6983 BOOL fullscreen
, ret
;
6988 memset(&devmode
, 0, sizeof(devmode
));
6989 devmode
.dmSize
= sizeof(devmode
);
6990 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode
);
6991 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
6992 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
6993 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode
);
6994 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
6995 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
6997 while (EnumDisplaySettingsW(NULL
, mode_idx
++, &devmode
))
6999 if (devmode
.dmPelsWidth
== registry_mode
.dmPelsWidth
7000 && devmode
.dmPelsHeight
== registry_mode
.dmPelsHeight
)
7003 if (!d3d_width
&& !d3d_height
)
7005 d3d_width
= devmode
.dmPelsWidth
;
7006 d3d_height
= devmode
.dmPelsHeight
;
7010 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7013 user32_width
= devmode
.dmPelsWidth
;
7014 user32_height
= devmode
.dmPelsHeight
;
7017 if (!user32_width
|| !user32_height
)
7019 skip("Failed to find three different display modes for the primary output.\n");
7023 ret
= save_display_modes(&original_modes
, &display_count
);
7024 ok(ret
, "Failed to save original display modes.\n");
7026 get_factory(device
, is_d3d12
, &factory
);
7028 /* Test that no mode restorations if no mode changes actually happened */
7029 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7030 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7032 swapchain_desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
7033 swapchain_desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
7034 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
7035 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
7036 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7037 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
7038 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
7039 swapchain_desc
.SampleDesc
.Count
= 1;
7040 swapchain_desc
.SampleDesc
.Quality
= 0;
7041 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7042 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
7043 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
7044 swapchain_desc
.Windowed
= TRUE
;
7045 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
7046 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
7048 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7049 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7050 refcount
= IDXGISwapChain_Release(swapchain
);
7051 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7053 memset(&devmode2
, 0, sizeof(devmode2
));
7054 devmode2
.dmSize
= sizeof(devmode2
);
7055 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7056 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7057 ok(equal_mode_rect(&devmode2
, ®istry_mode
), "Got a different mode.\n");
7058 ret
= restore_display_modes(original_modes
, display_count
);
7059 ok(ret
, "Failed to restore display modes.\n");
7061 /* If current display settings are different than the display settings in registry before
7062 * calling SetFullscreenState() */
7063 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7064 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7066 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7067 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7068 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7069 ok(hr
== DXGI_ERROR_UNSUPPORTED
/* Win7 */
7070 || hr
== S_OK
/* Win8~Win10 1909 */
7071 || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, /* Win10 2004 */
7072 "Got unexpected hr %#x.\n", hr
);
7074 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7075 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7076 refcount
= IDXGISwapChain_Release(swapchain
);
7077 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7078 ret
= restore_display_modes(original_modes
, display_count
);
7079 ok(ret
, "Failed to restore display modes.\n");
7081 /* Test that mode restorations use display settings in the registry with a fullscreen device */
7082 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7083 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7084 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7087 skip("SetFullscreenState failed, hr %#x.\n", hr
);
7088 refcount
= IDXGISwapChain_Release(swapchain
);
7089 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7093 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7094 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7095 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7096 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7098 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7099 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7100 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7101 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7102 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7103 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7104 refcount
= IDXGISwapChain_Release(swapchain
);
7105 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7106 ret
= restore_display_modes(original_modes
, display_count
);
7107 ok(ret
, "Failed to restore display modes.\n");
7109 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
)); ++adapter_idx
)
7111 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
)); ++output_idx
)
7113 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
7114 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_idx
, output_idx
, hr
);
7116 if ((adapter_idx
|| output_idx
) && output_desc
.AttachedToDesktop
)
7118 second_output
= output
;
7122 IDXGIOutput_Release(output
);
7125 IDXGIAdapter_Release(adapter
);
7132 skip("Following tests require two monitors.\n");
7135 lstrcpyW(second_monitor_name
, output_desc
.DeviceName
);
7137 memset(&old_devmode
, 0, sizeof(old_devmode
));
7138 old_devmode
.dmSize
= sizeof(old_devmode
);
7139 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &old_devmode
);
7140 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7147 while (EnumDisplaySettingsW(second_monitor_name
, mode_idx
++, &devmode
))
7149 if (devmode
.dmPelsWidth
== old_devmode
.dmPelsWidth
7150 && devmode
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7153 if (!d3d_width
&& !d3d_height
)
7155 d3d_width
= devmode
.dmPelsWidth
;
7156 d3d_height
= devmode
.dmPelsHeight
;
7160 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7163 user32_width
= devmode
.dmPelsWidth
;
7164 user32_height
= devmode
.dmPelsHeight
;
7167 if (!user32_width
|| !user32_height
)
7169 skip("Failed to find three different display modes for the second output.\n");
7173 /* Test that mode restorations for non-primary outputs upon fullscreen state changes */
7174 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7175 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7176 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7177 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7179 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
, CDS_RESET
, NULL
);
7180 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %d.\n", change_ret
);
7181 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7182 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7183 if (devmode2
.dmPelsWidth
== old_devmode
.dmPelsWidth
7184 && devmode2
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7186 skip("Failed to change display settings of the second monitor.\n");
7187 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7188 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7189 refcount
= IDXGISwapChain_Release(swapchain
);
7190 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7194 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7195 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7197 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7198 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7199 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7200 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7201 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7202 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7203 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7204 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7205 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7206 old_devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", old_devmode
.dmPelsWidth
,
7207 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7208 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7209 old_devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", old_devmode
.dmPelsHeight
,
7210 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7212 refcount
= IDXGISwapChain_Release(swapchain
);
7213 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7214 ret
= restore_display_modes(original_modes
, display_count
);
7215 ok(ret
, "Failed to restore display modes.\n");
7217 /* Test that mode restorations for non-primary outputs use display settings in the registry */
7218 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7219 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7220 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7221 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7223 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
,
7224 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
7225 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %d.\n", change_ret
);
7226 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7227 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7229 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7230 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7231 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7232 "Expected resolution %ux%u, got %ux%u.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7233 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7234 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7235 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7236 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7237 "Expected resolution %ux%u, got %ux%u.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7238 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7239 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7240 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7241 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7242 devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", devmode
.dmPelsWidth
,
7243 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7244 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7245 devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", devmode
.dmPelsHeight
,
7246 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7248 refcount
= IDXGISwapChain_Release(swapchain
);
7249 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7250 ret
= restore_display_modes(original_modes
, display_count
);
7251 ok(ret
, "Failed to restore display modes.\n");
7253 /* Test that mode restorations for non-primary outputs on fullscreen state changes when there
7254 * are two fullscreen swapchains on different outputs */
7255 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7256 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7258 swapchain_desc2
= swapchain_desc
;
7259 swapchain_desc
.BufferDesc
.Width
= d3d_width
;
7260 swapchain_desc
.BufferDesc
.Height
= d3d_height
;
7261 swapchain_desc2
.OutputWindow
= CreateWindowA("static", "dxgi_test2", 0,
7262 old_devmode
.dmPosition
.x
, old_devmode
.dmPosition
.y
, 400, 200, 0, 0, 0, 0);
7263 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc2
, &swapchain2
);
7264 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7265 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7266 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7267 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, TRUE
, NULL
);
7270 skip("SetFullscreenState failed, hr %#x.\n", hr
);
7271 refcount
= IDXGISwapChain_Release(swapchain2
);
7272 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7273 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7274 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7275 refcount
= IDXGISwapChain_Release(swapchain
);
7276 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7280 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7281 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7282 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
7283 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
7284 ok(!fullscreen
, "Expected swapchain not fullscreen.\n");
7285 hr
= IDXGISwapChain_GetFullscreenState(swapchain2
, &fullscreen
, NULL
);
7286 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
7287 ok(fullscreen
, "Expected swapchain fullscreen.\n");
7289 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7290 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7291 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7292 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7293 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7294 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7295 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7296 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7297 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7298 old_devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", old_devmode
.dmPelsWidth
,
7299 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7300 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7301 old_devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", old_devmode
.dmPelsHeight
,
7302 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7304 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, FALSE
, NULL
);
7305 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7306 refcount
= IDXGISwapChain_Release(swapchain2
);
7307 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7308 refcount
= IDXGISwapChain_Release(swapchain
);
7309 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7310 DestroyWindow(swapchain_desc2
.OutputWindow
);
7311 ret
= restore_display_modes(original_modes
, display_count
);
7312 ok(ret
, "Failed to restore display modes.\n");
7316 IDXGIOutput_Release(second_output
);
7317 DestroyWindow(swapchain_desc
.OutputWindow
);
7318 refcount
= IDXGIFactory_Release(factory
);
7319 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
7320 ret
= restore_display_modes(original_modes
, display_count
);
7321 ok(ret
, "Failed to restore display modes.\n");
7322 heap_free(original_modes
);
7325 static void run_on_d3d10(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7327 IDXGIDevice
*device
;
7330 if (!(device
= create_device(0)))
7332 skip("Failed to create Direct3D 10 device.\n");
7336 test_func((IUnknown
*)device
, FALSE
);
7338 refcount
= IDXGIDevice_Release(device
);
7339 ok(!refcount
, "Device has %u references left.\n", refcount
);
7342 static void run_on_d3d12(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7344 ID3D12CommandQueue
*queue
;
7345 ID3D12Device
*device
;
7348 if (!(device
= create_d3d12_device()))
7350 skip("Failed to create Direct3D 12 device.\n");
7354 queue
= create_d3d12_direct_queue(device
);
7356 test_func((IUnknown
*)queue
, TRUE
);
7358 wait_queue_idle(device
, queue
);
7360 refcount
= ID3D12CommandQueue_Release(queue
);
7361 ok(!refcount
, "Command queue has %u references left.\n", refcount
);
7362 refcount
= ID3D12Device_Release(device
);
7363 ok(!refcount
, "Device has %u references left.\n", refcount
);
7368 HMODULE dxgi_module
, d3d11_module
, d3d12_module
, gdi32_module
;
7369 BOOL enable_debug_layer
= FALSE
;
7370 unsigned int argc
, i
;
7374 dxgi_module
= GetModuleHandleA("dxgi.dll");
7375 pCreateDXGIFactory1
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory1");
7376 pCreateDXGIFactory2
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory2");
7378 gdi32_module
= GetModuleHandleA("gdi32.dll");
7379 pD3DKMTCheckVidPnExclusiveOwnership
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCheckVidPnExclusiveOwnership");
7380 pD3DKMTCloseAdapter
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCloseAdapter");
7381 pD3DKMTOpenAdapterFromGdiDisplayName
= (void *)GetProcAddress(gdi32_module
, "D3DKMTOpenAdapterFromGdiDisplayName");
7383 d3d11_module
= LoadLibraryA("d3d11.dll");
7384 pD3D11CreateDevice
= (void *)GetProcAddress(d3d11_module
, "D3D11CreateDevice");
7386 registry_mode
.dmSize
= sizeof(registry_mode
);
7387 ok(EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, ®istry_mode
), "Failed to get display mode.\n");
7389 use_mt
= !getenv("WINETEST_NO_MT_D3D");
7391 argc
= winetest_get_mainargs(&argv
);
7392 for (i
= 2; i
< argc
; ++i
)
7394 if (!strcmp(argv
[i
], "--validate"))
7395 enable_debug_layer
= TRUE
;
7396 else if (!strcmp(argv
[i
], "--warp"))
7397 use_warp_adapter
= TRUE
;
7398 else if (!strcmp(argv
[i
], "--adapter") && i
+ 1 < argc
)
7399 use_adapter_idx
= atoi(argv
[++i
]);
7400 else if (!strcmp(argv
[i
], "--single"))
7404 queue_test(test_adapter_desc
);
7405 queue_test(test_adapter_luid
);
7406 queue_test(test_query_video_memory_info
);
7407 queue_test(test_check_interface_support
);
7408 queue_test(test_create_surface
);
7409 queue_test(test_parents
);
7410 queue_test(test_output
);
7411 queue_test(test_find_closest_matching_mode
);
7412 queue_test(test_resize_target_wndproc
);
7413 queue_test(test_create_factory
);
7414 queue_test(test_private_data
);
7415 queue_test(test_maximum_frame_latency
);
7416 queue_test(test_output_desc
);
7417 queue_test(test_object_wrapping
);
7418 queue_test(test_factory_check_feature_support
);
7422 /* These tests use full-screen swapchains, so shouldn't run in parallel. */
7423 test_create_swapchain();
7424 test_inexact_modes();
7425 test_gamma_control();
7426 test_multi_adapter();
7427 test_swapchain_parameters();
7428 test_swapchain_window_messages();
7429 test_swapchain_window_styles();
7430 run_on_d3d10(test_set_fullscreen
);
7431 run_on_d3d10(test_resize_target
);
7432 run_on_d3d10(test_swapchain_resize
);
7433 run_on_d3d10(test_swapchain_present
);
7434 run_on_d3d10(test_swapchain_backbuffer_index
);
7435 run_on_d3d10(test_swapchain_formats
);
7436 run_on_d3d10(test_output_ownership
);
7437 run_on_d3d10(test_cursor_clipping
);
7438 run_on_d3d10(test_get_containing_output
);
7439 run_on_d3d10(test_window_association
);
7440 run_on_d3d10(test_default_fullscreen_target_output
);
7441 run_on_d3d10(test_mode_change
);
7443 if (!(d3d12_module
= LoadLibraryA("d3d12.dll")))
7445 skip("Direct3D 12 is not available.\n");
7449 pD3D12CreateDevice
= (void *)GetProcAddress(d3d12_module
, "D3D12CreateDevice");
7450 pD3D12GetDebugInterface
= (void *)GetProcAddress(d3d12_module
, "D3D12GetDebugInterface");
7452 if (enable_debug_layer
&& SUCCEEDED(pD3D12GetDebugInterface(&IID_ID3D12Debug
, (void **)&debug
)))
7454 ID3D12Debug_EnableDebugLayer(debug
);
7455 ID3D12Debug_Release(debug
);
7458 run_on_d3d12(test_set_fullscreen
);
7459 run_on_d3d12(test_resize_target
);
7460 run_on_d3d12(test_swapchain_resize
);
7461 run_on_d3d12(test_swapchain_present
);
7462 run_on_d3d12(test_swapchain_backbuffer_index
);
7463 run_on_d3d12(test_swapchain_formats
);
7464 run_on_d3d12(test_output_ownership
);
7465 run_on_d3d12(test_cursor_clipping
);
7466 run_on_d3d12(test_frame_latency_event
);
7467 run_on_d3d12(test_colour_space_support
);
7468 run_on_d3d12(test_get_containing_output
);
7469 run_on_d3d12(test_window_association
);
7470 run_on_d3d12(test_default_fullscreen_target_output
);
7471 run_on_d3d12(test_mode_change
);
7473 FreeLibrary(d3d12_module
);