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 #define create_swapchain(a, b, c) create_swapchain_(__LINE__, a, b, c)
912 static IDXGISwapChain
*create_swapchain_(unsigned int line
, IUnknown
*device
, BOOL is_d3d12
, HWND window
)
914 DXGI_SWAP_CHAIN_DESC desc
;
915 IDXGISwapChain
*swapchain
;
916 IDXGIFactory
*factory
;
919 desc
.BufferDesc
.Width
= 640;
920 desc
.BufferDesc
.Height
= 480;
921 desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
922 desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
923 desc
.BufferDesc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
924 desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
925 desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
926 desc
.SampleDesc
.Count
= 1;
927 desc
.SampleDesc
.Quality
= 0;
928 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
929 desc
.BufferCount
= is_d3d12
? 2 : 1;
930 desc
.OutputWindow
= window
;
931 desc
.Windowed
= TRUE
;
932 desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
935 get_factory(device
, is_d3d12
, &factory
);
936 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &desc
, &swapchain
);
937 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
938 IDXGIFactory_Release(factory
);
943 static void test_adapter_desc(void)
945 DXGI_ADAPTER_DESC1 desc1
;
946 IDXGIAdapter1
*adapter1
;
947 DXGI_ADAPTER_DESC desc
;
948 IDXGIAdapter
*adapter
;
953 if (!(device
= create_device(0)))
955 skip("Failed to create device.\n");
959 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
960 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
962 hr
= IDXGIAdapter_GetDesc(adapter
, NULL
);
963 ok(hr
== E_INVALIDARG
, "GetDesc returned %#x, expected %#x.\n",
966 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
967 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
969 trace("%s.\n", wine_dbgstr_w(desc
.Description
));
970 trace("%04x: %04x:%04x (rev %02x).\n",
971 desc
.SubSysId
, desc
.VendorId
, desc
.DeviceId
, desc
.Revision
);
972 trace("Dedicated video memory: %lu (%lu MB).\n",
973 desc
.DedicatedVideoMemory
, desc
.DedicatedVideoMemory
/ (1024 * 1024));
974 trace("Dedicated system memory: %lu (%lu MB).\n",
975 desc
.DedicatedSystemMemory
, desc
.DedicatedSystemMemory
/ (1024 * 1024));
976 trace("Shared system memory: %lu (%lu MB).\n",
977 desc
.SharedSystemMemory
, desc
.SharedSystemMemory
/ (1024 * 1024));
978 trace("LUID: %08x:%08x.\n", desc
.AdapterLuid
.HighPart
, desc
.AdapterLuid
.LowPart
);
980 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
981 ok(SUCCEEDED(hr
) || broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#x.\n", hr
);
982 if (hr
== E_NOINTERFACE
)
985 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &desc1
);
986 ok(SUCCEEDED(hr
), "GetDesc1 failed, hr %#x.\n", hr
);
988 ok(!lstrcmpW(desc
.Description
, desc1
.Description
),
989 "Got unexpected description %s.\n", wine_dbgstr_w(desc1
.Description
));
990 ok(desc1
.VendorId
== desc
.VendorId
, "Got unexpected vendor ID %04x.\n", desc1
.VendorId
);
991 ok(desc1
.DeviceId
== desc
.DeviceId
, "Got unexpected device ID %04x.\n", desc1
.DeviceId
);
992 ok(desc1
.SubSysId
== desc
.SubSysId
, "Got unexpected sub system ID %04x.\n", desc1
.SubSysId
);
993 ok(desc1
.Revision
== desc
.Revision
, "Got unexpected revision %02x.\n", desc1
.Revision
);
994 ok(desc1
.DedicatedVideoMemory
== desc
.DedicatedVideoMemory
,
995 "Got unexpected dedicated video memory %lu.\n", desc1
.DedicatedVideoMemory
);
996 ok(desc1
.DedicatedSystemMemory
== desc
.DedicatedSystemMemory
,
997 "Got unexpected dedicated system memory %lu.\n", desc1
.DedicatedSystemMemory
);
998 ok(desc1
.SharedSystemMemory
== desc
.SharedSystemMemory
,
999 "Got unexpected shared system memory %lu.\n", desc1
.SharedSystemMemory
);
1000 ok(equal_luid(desc1
.AdapterLuid
, desc
.AdapterLuid
),
1001 "Got unexpected adapter LUID %08x:%08x.\n", desc1
.AdapterLuid
.HighPart
, desc1
.AdapterLuid
.LowPart
);
1002 trace("Flags: %08x.\n", desc1
.Flags
);
1004 IDXGIAdapter1_Release(adapter1
);
1007 IDXGIAdapter_Release(adapter
);
1008 refcount
= IDXGIDevice_Release(device
);
1009 ok(!refcount
, "Device has %u references left.\n", refcount
);
1012 static void test_adapter_luid(void)
1014 DXGI_ADAPTER_DESC device_adapter_desc
, desc
, desc2
;
1015 static const LUID luid
= {0xdeadbeef, 0xdeadbeef};
1016 IDXGIAdapter
*adapter
, *adapter2
;
1017 unsigned int found_adapter_count
;
1018 unsigned int adapter_index
;
1019 BOOL is_null_luid_adapter
;
1020 IDXGIFactory4
*factory4
;
1021 IDXGIFactory
*factory
;
1022 BOOL have_unique_luid
;
1023 IDXGIDevice
*device
;
1027 if (!(device
= create_device(0)))
1029 skip("Failed to create device.\n");
1033 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1034 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1035 hr
= IDXGIAdapter_GetDesc(adapter
, &device_adapter_desc
);
1036 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1037 IDXGIAdapter_Release(adapter
);
1038 refcount
= IDXGIDevice_Release(device
);
1039 ok(!refcount
, "Device has %u references left.\n", refcount
);
1041 is_null_luid_adapter
= !device_adapter_desc
.AdapterLuid
.LowPart
1042 && !device_adapter_desc
.SubSysId
&& !device_adapter_desc
.Revision
1043 && !device_adapter_desc
.VendorId
&& !device_adapter_desc
.DeviceId
;
1045 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
1046 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
1048 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory4
, (void **)&factory4
);
1049 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
1051 have_unique_luid
= TRUE
;
1052 found_adapter_count
= 0;
1054 while ((hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)) == S_OK
)
1056 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1057 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1059 if (equal_luid(desc
.AdapterLuid
, device_adapter_desc
.AdapterLuid
))
1061 check_adapter_desc(&desc
, &device_adapter_desc
);
1062 ++found_adapter_count
;
1065 if (equal_luid(desc
.AdapterLuid
, luid
))
1066 have_unique_luid
= FALSE
;
1070 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, desc
.AdapterLuid
,
1071 &IID_IDXGIAdapter
, (void **)&adapter2
);
1072 ok(hr
== S_OK
, "Failed to enum adapter by LUID, hr %#x.\n", hr
);
1073 hr
= IDXGIAdapter_GetDesc(adapter2
, &desc2
);
1074 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1075 check_adapter_desc(&desc2
, &desc
);
1076 ok(adapter2
!= adapter
, "Expected to get new instance of IDXGIAdapter.\n");
1077 refcount
= IDXGIAdapter_Release(adapter2
);
1078 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1081 refcount
= IDXGIAdapter_Release(adapter
);
1082 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1086 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
1088 /* Older versions of WARP aren't enumerated by IDXGIFactory_EnumAdapters(). */
1089 ok(found_adapter_count
== 1 || broken(is_null_luid_adapter
),
1090 "Found %u adapters for LUID %08x:%08x.\n",
1091 found_adapter_count
, device_adapter_desc
.AdapterLuid
.HighPart
,
1092 device_adapter_desc
.AdapterLuid
.LowPart
);
1095 IDXGIFactory4_Release(factory4
);
1096 refcount
= IDXGIFactory_Release(factory
);
1097 ok(!refcount
, "Factory has %u references left.\n", refcount
);
1099 if (!pCreateDXGIFactory2
1100 || FAILED(hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory4
, (void **)&factory4
)))
1102 skip("DXGI 1.4 is not available.\n");
1106 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1107 &IID_IDXGIAdapter
, NULL
);
1108 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1110 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1111 &IID_IDXGIAdapter
, (void **)&adapter
);
1112 ok(hr
== S_OK
, "Failed to enum adapter by LUID, hr %#x.\n", hr
);
1115 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1116 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
1117 check_adapter_desc(&desc
, &device_adapter_desc
);
1118 refcount
= IDXGIAdapter_Release(adapter
);
1119 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
1122 if (have_unique_luid
)
1124 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, luid
, &IID_IDXGIAdapter
, (void **)&adapter
);
1125 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
1129 skip("Our LUID is not unique.\n");
1132 refcount
= IDXGIFactory4_Release(factory4
);
1133 ok(!refcount
, "Factory has %u references left.\n", refcount
);
1136 static void test_query_video_memory_info(void)
1138 DXGI_QUERY_VIDEO_MEMORY_INFO memory_info
;
1139 IDXGIAdapter3
*adapter3
;
1140 IDXGIAdapter
*adapter
;
1141 IDXGIDevice
*device
;
1145 if (!(device
= create_device(0)))
1147 skip("Failed to create device.\n");
1151 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1152 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1153 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter3
, (void **)&adapter3
);
1154 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
1155 if (hr
== E_NOINTERFACE
)
1158 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL
, &memory_info
);
1159 ok(hr
== S_OK
, "Failed to query video memory info, hr %#x.\n", hr
);
1160 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1161 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1162 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1163 wine_dbgstr_longlong(memory_info
.Budget
));
1164 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1165 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1167 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
, &memory_info
);
1168 ok(hr
== S_OK
, "Failed to query video memory info, hr %#x.\n", hr
);
1169 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1170 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1171 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1172 wine_dbgstr_longlong(memory_info
.Budget
));
1173 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1174 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1176 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
+ 1, &memory_info
);
1177 ok(hr
== E_INVALIDARG
, "Failed to query video memory info, hr %#x.\n", hr
);
1179 IDXGIAdapter3_Release(adapter3
);
1182 IDXGIAdapter_Release(adapter
);
1183 refcount
= IDXGIDevice_Release(device
);
1184 ok(!refcount
, "Device has %u references left.\n", refcount
);
1187 static void test_check_interface_support(void)
1189 LARGE_INTEGER driver_version
;
1190 IDXGIAdapter
*adapter
;
1191 IDXGIDevice
*device
;
1196 if (!(device
= create_device(0)))
1198 skip("Failed to create device.\n");
1202 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1203 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1205 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, NULL
);
1206 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1207 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, &driver_version
);
1208 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1209 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, NULL
);
1210 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1211 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, &driver_version
);
1212 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1214 trace("UMD version: %u.%u.%u.%u.\n",
1215 HIWORD(U(driver_version
).HighPart
), LOWORD(U(driver_version
).HighPart
),
1216 HIWORD(U(driver_version
).LowPart
), LOWORD(U(driver_version
).LowPart
));
1218 hr
= IDXGIDevice_QueryInterface(device
, &IID_ID3D10Device1
, (void **)&iface
);
1221 IUnknown_Release(iface
);
1222 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, NULL
);
1223 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1224 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, &driver_version
);
1225 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1229 win_skip("D3D10.1 is not supported.\n");
1232 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, NULL
);
1233 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#x.\n", hr
);
1234 driver_version
.LowPart
= driver_version
.HighPart
= 0xdeadbeef;
1235 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, &driver_version
);
1236 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#x.\n", hr
);
1237 ok(driver_version
.HighPart
== 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version
.HighPart
);
1238 ok(driver_version
.LowPart
== 0xdeadbeef, "Got unexpected driver version %#x.\n", driver_version
.LowPart
);
1240 IDXGIAdapter_Release(adapter
);
1241 refcount
= IDXGIDevice_Release(device
);
1242 ok(!refcount
, "Device has %u references left.\n", refcount
);
1245 static void test_create_surface(void)
1247 ID3D11Texture2D
*texture2d
;
1248 DXGI_SURFACE_DESC desc
;
1249 IDXGISurface
*surface
;
1250 IDXGIDevice
*device
;
1254 if (!(device
= create_device(0)))
1256 skip("Failed to create device.\n");
1262 desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1263 desc
.SampleDesc
.Count
= 1;
1264 desc
.SampleDesc
.Quality
= 0;
1266 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1267 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1269 check_interface(surface
, &IID_ID3D10Texture2D
, TRUE
, FALSE
);
1270 /* Not available on all Windows versions. */
1271 check_interface(surface
, &IID_ID3D11Texture2D
, TRUE
, TRUE
);
1272 /* Not available on all Windows versions. */
1273 check_interface(surface
, &IID_IDXGISurface1
, TRUE
, TRUE
);
1275 IDXGISurface_Release(surface
);
1276 refcount
= IDXGIDevice_Release(device
);
1277 ok(!refcount
, "Device has %u references left.\n", refcount
);
1279 /* DXGI_USAGE_UNORDERED_ACCESS */
1280 if (!(device
= create_d3d11_device()))
1282 skip("Failed to create D3D11 device.\n");
1287 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_UNORDERED_ACCESS
, NULL
, &surface
);
1288 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1292 ID3D11UnorderedAccessView
*uav
;
1293 ID3D11Device
*d3d_device
;
1295 hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture2d
);
1296 ok(SUCCEEDED(hr
), "Failed to get texture interface, hr %#x.\n", hr
);
1298 ID3D11Texture2D_GetDevice(texture2d
, &d3d_device
);
1300 hr
= ID3D11Device_CreateUnorderedAccessView(d3d_device
, (ID3D11Resource
*)texture2d
, NULL
, &uav
);
1301 ok(SUCCEEDED(hr
), "Failed to create unordered access view, hr %#x.\n", hr
);
1302 ID3D11UnorderedAccessView_Release(uav
);
1304 ID3D11Device_Release(d3d_device
);
1305 ID3D11Texture2D_Release(texture2d
);
1307 IDXGISurface_Release(surface
);
1310 refcount
= IDXGIDevice_Release(device
);
1311 ok(!refcount
, "Device has %u references left.\n", refcount
);
1314 static void test_parents(void)
1316 DXGI_SURFACE_DESC surface_desc
;
1317 IDXGISurface
*surface
;
1318 IDXGIFactory
*factory
;
1319 IDXGIAdapter
*adapter
;
1320 IDXGIDevice
*device
;
1321 IDXGIOutput
*output
;
1326 if (!(device
= create_device(0)))
1328 skip("Failed to create device.\n");
1332 surface_desc
.Width
= 512;
1333 surface_desc
.Height
= 512;
1334 surface_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1335 surface_desc
.SampleDesc
.Count
= 1;
1336 surface_desc
.SampleDesc
.Quality
= 0;
1338 hr
= IDXGIDevice_CreateSurface(device
, &surface_desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1339 ok(SUCCEEDED(hr
), "Failed to create a dxgi surface, hr %#x\n", hr
);
1341 hr
= IDXGISurface_GetParent(surface
, &IID_IDXGIDevice
, (void **)&parent
);
1342 IDXGISurface_Release(surface
);
1343 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1344 ok(parent
== (IUnknown
*)device
, "Got parent %p, expected %p.\n", parent
, device
);
1345 IUnknown_Release(parent
);
1347 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1348 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1350 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1351 if (hr
== DXGI_ERROR_NOT_FOUND
)
1353 skip("Adapter has not outputs.\n");
1357 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1359 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&parent
);
1360 IDXGIOutput_Release(output
);
1361 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1362 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1363 IUnknown_Release(parent
);
1366 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1367 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1369 hr
= IDXGIFactory_GetParent(factory
, &IID_IUnknown
, (void **)&parent
);
1370 ok(hr
== E_NOINTERFACE
, "GetParent returned %#x, expected %#x.\n", hr
, E_NOINTERFACE
);
1371 ok(parent
== NULL
, "Got parent %p, expected %p.\n", parent
, NULL
);
1372 IDXGIFactory_Release(factory
);
1374 hr
= IDXGIDevice_GetParent(device
, &IID_IDXGIAdapter
, (void **)&parent
);
1375 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
1376 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1377 IUnknown_Release(parent
);
1379 IDXGIAdapter_Release(adapter
);
1380 refcount
= IDXGIDevice_Release(device
);
1381 ok(!refcount
, "Device has %u references left.\n", refcount
);
1384 static void test_output(void)
1386 unsigned int mode_count
, mode_count_comp
, i
, last_height
, last_width
;
1387 double last_refresh_rate
;
1388 IDXGIAdapter
*adapter
;
1389 IDXGIDevice
*device
;
1391 IDXGIOutput
*output
;
1393 DXGI_MODE_DESC
*modes
;
1395 if (!(device
= create_device(0)))
1397 skip("Failed to create device.\n");
1401 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1402 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1404 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, NULL
);
1405 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1407 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1408 if (hr
== DXGI_ERROR_NOT_FOUND
)
1410 skip("Adapter doesn't have any outputs.\n");
1411 IDXGIAdapter_Release(adapter
);
1412 IDXGIDevice_Release(device
);
1415 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1417 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, NULL
, NULL
);
1418 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1420 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1422 || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Remote Desktop Services / Win 7 testbot */
1423 "Failed to list modes, hr %#x.\n", hr
);
1424 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1426 win_skip("GetDisplayModeList() not supported.\n");
1427 IDXGIOutput_Release(output
);
1428 IDXGIAdapter_Release(adapter
);
1429 IDXGIDevice_Release(device
);
1432 mode_count_comp
= mode_count
;
1434 hr
= IDXGIOutput_GetDisplayModeList(output
, 0, 0, &mode_count
, NULL
);
1435 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1436 ok(!mode_count
, "Got unexpected mode_count %u.\n", mode_count
);
1438 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1439 DXGI_ENUM_MODES_SCALING
, &mode_count
, NULL
);
1440 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1441 ok(mode_count
>= mode_count_comp
, "Got unexpected mode_count %u, expected >= %u.\n", mode_count
, mode_count_comp
);
1442 mode_count_comp
= mode_count
;
1444 modes
= heap_calloc(mode_count
+ 10, sizeof(*modes
));
1445 ok(!!modes
, "Failed to allocate memory.\n");
1447 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1448 DXGI_ENUM_MODES_SCALING
, NULL
, modes
);
1449 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1450 ok(!modes
[0].Height
, "No output was expected.\n");
1453 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1454 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1455 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
1456 ok(!modes
[0].Height
, "No output was expected.\n");
1458 mode_count
= mode_count_comp
;
1459 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1460 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1461 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1462 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1464 last_width
= last_height
= 0;
1465 last_refresh_rate
= 0.;
1466 for (i
= 0; i
< mode_count
; i
++)
1468 double refresh_rate
= modes
[i
].RefreshRate
.Numerator
/ (double)modes
[i
].RefreshRate
.Denominator
;
1470 ok(modes
[i
].Width
&& modes
[i
].Height
, "Mode %u: Invalid dimensions %ux%u.\n",
1471 i
, modes
[i
].Width
, modes
[i
].Height
);
1473 ok(modes
[i
].Width
>= last_width
,
1474 "Mode %u: Modes should have been sorted, width %u < %u.\n", i
, modes
[i
].Width
, last_width
);
1475 if (modes
[i
].Width
!= last_width
)
1477 last_width
= modes
[i
].Width
;
1479 last_refresh_rate
= 0.;
1483 ok(modes
[i
].Height
>= last_height
,
1484 "Mode %u: Modes should have been sorted, height %u < %u.\n", i
, modes
[i
].Height
, last_height
);
1485 if (modes
[i
].Height
!= last_height
)
1487 last_height
= modes
[i
].Height
;
1488 last_refresh_rate
= 0.;
1492 ok(refresh_rate
>= last_refresh_rate
,
1493 "Mode %u: Modes should have been sorted, refresh rate %f < %f.\n", i
, refresh_rate
, last_refresh_rate
);
1494 if (refresh_rate
!= last_refresh_rate
)
1495 last_refresh_rate
= refresh_rate
;
1499 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1500 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1501 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1502 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1504 if (mode_count_comp
)
1506 mode_count
= mode_count_comp
- 1;
1507 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1508 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1509 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
1510 ok(mode_count
== mode_count_comp
- 1, "Got unexpected mode_count %u, expected %u.\n",
1511 mode_count
, mode_count_comp
- 1);
1515 skip("Not enough modes for test.\n");
1519 IDXGIOutput_Release(output
);
1520 IDXGIAdapter_Release(adapter
);
1521 refcount
= IDXGIDevice_Release(device
);
1522 ok(!refcount
, "Device has %u references left.\n", refcount
);
1525 static void test_find_closest_matching_mode(void)
1527 static const DXGI_MODE_SCALING scaling_tests
[] =
1529 DXGI_MODE_SCALING_CENTERED
,
1530 DXGI_MODE_SCALING_STRETCHED
1532 DXGI_MODE_DESC
*modes
, mode
, matching_mode
;
1533 unsigned int i
, j
, mode_count
;
1534 IDXGIAdapter
*adapter
;
1535 IDXGIDevice
*device
;
1536 IDXGIOutput
*output
;
1540 if (!(device
= create_device(0)))
1542 skip("Failed to create device.\n");
1546 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1547 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
1549 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1550 if (hr
== DXGI_ERROR_NOT_FOUND
)
1552 win_skip("Adapter doesn't have any outputs.\n");
1553 IDXGIAdapter_Release(adapter
);
1554 IDXGIDevice_Release(device
);
1557 ok(SUCCEEDED(hr
), "EnumOutputs failed, hr %#x.\n", hr
);
1559 memset(&mode
, 0, sizeof(mode
));
1560 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1561 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
1562 "Got unexpected hr %#x.\n", hr
);
1563 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1565 win_skip("FindClosestMatchingMode() not supported.\n");
1569 memset(&mode
, 0, sizeof(mode
));
1570 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, (IUnknown
*)device
);
1571 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1573 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1574 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1576 modes
= heap_calloc(mode_count
, sizeof(*modes
));
1577 ok(!!modes
, "Failed to allocate memory.\n");
1579 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
1580 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
1582 for (i
= 0; i
< mode_count
; ++i
)
1585 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1586 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1587 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
);
1589 mode
.Format
= DXGI_FORMAT_UNKNOWN
;
1590 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1591 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1595 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1596 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1600 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1601 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1604 mode
.Width
= mode
.Height
= 0;
1605 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1606 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1607 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_RESOLUTION
);
1608 ok(matching_mode
.Width
> 0 && matching_mode
.Height
> 0, "Got unexpected resolution %ux%u.\n",
1609 matching_mode
.Width
, matching_mode
.Height
);
1612 mode
.RefreshRate
.Numerator
= mode
.RefreshRate
.Denominator
= 0;
1613 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1614 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1615 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_REFRESH_RATE
);
1616 ok(matching_mode
.RefreshRate
.Numerator
> 0 && matching_mode
.RefreshRate
.Denominator
> 0,
1617 "Got unexpected refresh rate %u / %u.\n",
1618 matching_mode
.RefreshRate
.Numerator
, matching_mode
.RefreshRate
.Denominator
);
1621 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1622 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1623 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1624 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1625 ok(matching_mode
.ScanlineOrdering
, "Got unexpected scanline ordering %#x.\n",
1626 matching_mode
.ScanlineOrdering
);
1628 memset(&mode
, 0, sizeof(mode
));
1629 mode
.Width
= modes
[i
].Width
;
1630 mode
.Height
= modes
[i
].Height
;
1631 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1632 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1633 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1634 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1636 memset(&mode
, 0, sizeof(mode
));
1637 mode
.Width
= modes
[i
].Width
- 1;
1638 mode
.Height
= modes
[i
].Height
- 1;
1639 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1640 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1641 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1642 check_mode_desc(&matching_mode
, &modes
[i
],
1643 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1645 memset(&mode
, 0, sizeof(mode
));
1646 mode
.Width
= modes
[i
].Width
+ 1;
1647 mode
.Height
= modes
[i
].Height
+ 1;
1648 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1649 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1650 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1651 check_mode_desc(&matching_mode
, &modes
[i
],
1652 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1655 memset(&mode
, 0, sizeof(mode
));
1656 mode
.Width
= mode
.Height
= 10;
1657 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1658 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1659 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1660 /* Find mode for the lowest resolution. */
1662 for (i
= 0; i
< mode_count
; ++i
)
1664 if (mode
.Width
>= modes
[i
].Width
&& mode
.Height
>= modes
[i
].Height
)
1667 check_mode_desc(&matching_mode
, &mode
, MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1669 memset(&mode
, 0, sizeof(mode
));
1670 mode
.Width
= modes
[0].Width
;
1671 mode
.Height
= modes
[0].Height
;
1672 mode
.Format
= modes
[0].Format
;
1673 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST
;
1674 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1675 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1676 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1678 memset(&mode
, 0, sizeof(mode
));
1679 mode
.Width
= modes
[0].Width
;
1680 mode
.Height
= modes
[0].Height
;
1681 mode
.Format
= modes
[0].Format
;
1682 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST
;
1683 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1684 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1685 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1687 for (i
= 0; i
< ARRAY_SIZE(scaling_tests
); ++i
)
1689 for (j
= 0; j
< mode_count
; ++j
)
1691 if (modes
[j
].Scaling
!= scaling_tests
[i
])
1694 memset(&mode
, 0, sizeof(mode
));
1695 mode
.Width
= modes
[j
].Width
;
1696 mode
.Height
= modes
[j
].Height
;
1697 mode
.Format
= modes
[j
].Format
;
1698 mode
.Scaling
= modes
[j
].Scaling
;
1699 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1700 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1701 check_mode_desc(&matching_mode
, &modes
[j
],
1702 MODE_DESC_IGNORE_REFRESH_RATE
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1710 IDXGIOutput_Release(output
);
1711 IDXGIAdapter_Release(adapter
);
1712 refcount
= IDXGIDevice_Release(device
);
1713 ok(!refcount
, "Device has %u references left.\n", refcount
);
1716 struct refresh_rates
1720 BOOL numerator_should_pass
;
1721 BOOL denominator_should_pass
;
1724 static void test_create_swapchain(void)
1726 struct swapchain_fullscreen_state initial_state
, expected_state
;
1727 unsigned int i
, expected_width
, expected_height
;
1728 DXGI_SWAP_CHAIN_DESC creation_desc
, result_desc
;
1729 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc
;
1730 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
1731 IDXGIDevice
*device
, *bgra_device
;
1732 ULONG refcount
, expected_refcount
;
1733 IUnknown
*obj
, *obj2
, *parent
;
1734 IDXGISwapChain1
*swapchain1
;
1735 RECT
*expected_client_rect
;
1736 IDXGISwapChain
*swapchain
;
1737 IDXGISurface1
*surface
;
1738 IDXGIAdapter
*adapter
;
1739 IDXGIFactory
*factory
;
1740 IDXGIOutput
*target
;
1745 const struct refresh_rates refresh_list
[] =
1747 {60, 60, FALSE
, FALSE
},
1748 {60, 0, TRUE
, FALSE
},
1749 {60, 1, TRUE
, TRUE
},
1750 { 0, 60, TRUE
, FALSE
},
1751 { 0, 0, TRUE
, FALSE
},
1754 if (!(device
= create_device(0)))
1756 skip("Failed to create device.\n");
1760 creation_desc
.BufferDesc
.Width
= 800;
1761 creation_desc
.BufferDesc
.Height
= 600;
1762 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
1763 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
1764 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1765 creation_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1766 creation_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
1767 creation_desc
.SampleDesc
.Count
= 1;
1768 creation_desc
.SampleDesc
.Quality
= 0;
1769 creation_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1770 creation_desc
.BufferCount
= 1;
1771 creation_desc
.OutputWindow
= NULL
;
1772 creation_desc
.Windowed
= TRUE
;
1773 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
1774 creation_desc
.Flags
= 0;
1776 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
1777 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1779 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1780 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
1782 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1783 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
1785 expected_refcount
= get_refcount(adapter
);
1786 refcount
= get_refcount(factory
);
1787 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1788 refcount
= get_refcount(device
);
1789 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1791 creation_desc
.OutputWindow
= NULL
;
1792 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1793 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1795 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1796 memset(&initial_state
, 0, sizeof(initial_state
));
1797 capture_fullscreen_state(&initial_state
.fullscreen_state
, creation_desc
.OutputWindow
);
1799 hr
= IDXGIFactory_CreateSwapChain(factory
, NULL
, &creation_desc
, &swapchain
);
1800 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1801 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, NULL
, &swapchain
);
1802 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1803 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, NULL
);
1804 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
1805 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1806 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1808 refcount
= get_refcount(adapter
);
1809 ok(refcount
>= expected_refcount
, "Got refcount %u, expected >= %u.\n", refcount
, expected_refcount
);
1810 refcount
= get_refcount(factory
);
1811 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1812 refcount
= get_refcount(device
);
1813 ok(refcount
== 3, "Got unexpected refcount %u.\n", refcount
);
1815 hr
= IDXGISwapChain_GetDesc(swapchain
, NULL
);
1816 ok(hr
== E_INVALIDARG
, "GetDesc unexpectedly returned %#x.\n", hr
);
1818 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IUnknown
, (void **)&parent
);
1819 ok(hr
== S_OK
, "Failed to get parent,%#x.\n", hr
);
1820 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1821 refcount
= IUnknown_Release(parent
);
1822 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1824 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IDXGIFactory
, (void **)&parent
);
1825 ok(hr
== S_OK
, "Failed to get parent,%#x.\n", hr
);
1826 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1827 refcount
= IUnknown_Release(parent
);
1828 todo_wine
ok(refcount
== 4, "Got unexpected refcount %u.\n", refcount
);
1830 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain1
, (void **)&swapchain1
);
1831 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
1832 "Failed to query IDXGISwapChain1 interface, hr %#x.\n", hr
);
1835 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, NULL
);
1836 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1837 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, &swapchain_desc
);
1838 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1839 ok(!swapchain_desc
.Stereo
, "Got unexpected stereo %#x.\n", swapchain_desc
.Stereo
);
1840 ok(swapchain_desc
.Scaling
== DXGI_SCALING_STRETCH
,
1841 "Got unexpected scaling %#x.\n", swapchain_desc
.Scaling
);
1842 ok(swapchain_desc
.AlphaMode
== DXGI_ALPHA_MODE_IGNORE
,
1843 "Got unexpected alpha mode %#x.\n", swapchain_desc
.AlphaMode
);
1844 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, NULL
);
1845 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
1846 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, &fullscreen_desc
);
1847 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1848 ok(fullscreen_desc
.Windowed
== creation_desc
.Windowed
,
1849 "Got unexpected windowed %#x.\n", fullscreen_desc
.Windowed
);
1850 hr
= IDXGISwapChain1_GetHwnd(swapchain1
, &window
);
1851 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
1852 ok(window
== creation_desc
.OutputWindow
, "Got unexpected window %p.\n", window
);
1853 IDXGISwapChain1_Release(swapchain1
);
1856 refcount
= IDXGISwapChain_Release(swapchain
);
1857 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
1859 refcount
= get_refcount(factory
);
1860 ok(refcount
== 2, "Got unexpected refcount %u.\n", refcount
);
1862 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1864 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1865 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1867 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1868 ok(hr
== S_OK
, "Test %u: Failed to create swapchain, hr %#x.\n", i
, hr
);
1870 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1871 ok(hr
== S_OK
, "Test %u: Failed to get swapchain desc, hr %#x.\n", i
, hr
);
1873 ok(result_desc
.Windowed
== creation_desc
.Windowed
, "Test %u: Got unexpected windowed %#x.\n",
1874 i
, result_desc
.Windowed
);
1876 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1877 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1878 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1880 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1881 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1882 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1884 fullscreen
= 0xdeadbeef;
1885 target
= (void *)0xdeadbeef;
1886 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1887 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
1888 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1889 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1891 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
1892 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1893 fullscreen
= 0xdeadbeef;
1894 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
1895 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1896 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1897 target
= (void *)0xdeadbeef;
1898 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
1899 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
1900 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1902 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
1903 IDXGISwapChain_Release(swapchain
);
1906 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
1908 /* Test GDI-compatible swapchain */
1909 bgra_device
= create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT
);
1910 ok(!!bgra_device
, "Failed to create BGRA capable device.\n");
1912 hr
= IDXGIDevice_QueryInterface(bgra_device
, &IID_IUnknown
, (void **)&obj2
);
1913 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1915 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1916 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1918 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1923 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1924 ok(FAILED(hr
), "Expected GetDC() to fail, %#x\n", hr
);
1926 IDXGISurface1_Release(surface
);
1927 IDXGISwapChain_Release(swapchain
);
1929 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
1930 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE
;
1932 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1933 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
1935 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1936 creation_desc
.Flags
= 0;
1938 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1939 ok(hr
== S_OK
, "Failed to get front buffer, hr %#x.\n", hr
);
1941 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1942 ok(hr
== S_OK
, "Expected GetDC() to succeed, %#x\n", hr
);
1943 IDXGISurface1_ReleaseDC(surface
, NULL
);
1945 IDXGISurface1_Release(surface
);
1946 IDXGISwapChain_Release(swapchain
);
1950 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1951 IDXGISwapChain_Release(swapchain
);
1953 IUnknown_Release(obj2
);
1954 IDXGIDevice_Release(bgra_device
);
1956 creation_desc
.Windowed
= FALSE
;
1958 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1960 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1961 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1963 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1964 ok(SUCCEEDED(hr
), "Test %u: Failed to create swapchain, hr %#x.\n", i
, hr
);
1966 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1967 ok(hr
== S_OK
, "Test %u: Failed to get swapchain desc, hr %#x.\n", i
, hr
);
1969 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1970 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1971 if (result_desc
.Windowed
!= creation_desc
.Windowed
)
1972 trace("Test %u: Failed to change fullscreen state.\n", i
);
1974 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1975 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1976 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1978 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1979 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1980 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1984 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1985 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
1986 ok(fullscreen
== !result_desc
.Windowed
, "Test %u: Got fullscreen %#x, expected %#x.\n",
1987 i
, fullscreen
, result_desc
.Windowed
);
1988 ok(result_desc
.Windowed
? !target
: !!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1989 if (!result_desc
.Windowed
)
1991 IDXGIOutput
*containing_output
;
1992 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
1993 ok(hr
== S_OK
, "Test %u: Failed to get containing output, hr %#x.\n", i
, hr
);
1994 ok(containing_output
== target
, "Test %u: Got unexpected containing output pointer %p.\n",
1995 i
, containing_output
);
1996 IDXGIOutput_Release(containing_output
);
1998 ok(output_belongs_to_adapter(target
, adapter
),
1999 "Test %u: Output %p doesn't belong to adapter %p.\n",
2000 i
, target
, adapter
);
2001 IDXGIOutput_Release(target
);
2003 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
2004 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
2006 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2007 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
2008 ok(fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2010 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2011 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
2012 ok(!!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2013 IDXGIOutput_Release(target
);
2016 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2017 ok(hr
== S_OK
, "Test %u: Failed to set fullscreen state, hr %#x.\n", i
, hr
);
2019 fullscreen
= 0xdeadbeef;
2020 target
= (void *)0xdeadbeef;
2021 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
2022 ok(hr
== S_OK
, "Test %u: Failed to get fullscreen state, hr %#x.\n", i
, hr
);
2023 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2024 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2026 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2027 IDXGISwapChain_Release(swapchain
);
2030 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2032 /* Test swapchain creation with DXGI_FORMAT_UNKNOWN. */
2033 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_UNKNOWN
;
2034 creation_desc
.Windowed
= TRUE
;
2035 creation_desc
.Flags
= 0;
2036 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2037 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
2039 creation_desc
.Windowed
= FALSE
;
2040 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2041 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
2043 creation_desc
.BufferCount
= 2;
2044 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
2045 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2046 ok(hr
== E_INVALIDARG
|| hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
2047 creation_desc
.BufferCount
= 1;
2048 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
2050 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2052 /* Test swapchain creation with backbuffer width and height equal to 0. */
2053 expected_state
= initial_state
;
2054 expected_client_rect
= &expected_state
.fullscreen_state
.client_rect
;
2057 expected_width
= expected_client_rect
->right
;
2058 expected_height
= expected_client_rect
->bottom
;
2060 creation_desc
.BufferDesc
.Width
= 0;
2061 creation_desc
.BufferDesc
.Height
= 0;
2062 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2063 creation_desc
.Windowed
= TRUE
;
2064 creation_desc
.Flags
= 0;
2065 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2066 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2067 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2068 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2069 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2070 result_desc
.BufferDesc
.Width
, expected_width
);
2071 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2072 result_desc
.BufferDesc
.Height
, expected_height
);
2073 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2074 IDXGISwapChain_Release(swapchain
);
2076 DestroyWindow(creation_desc
.OutputWindow
);
2077 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2078 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
2079 0, 0, 222, 222, 0, 0, 0, 0);
2080 expected_state
.fullscreen_state
.style
= WS_CLIPSIBLINGS
| WS_CAPTION
2081 | WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
2082 SetRect(&expected_state
.fullscreen_state
.window_rect
, 0, 0, 222, 222);
2083 GetClientRect(creation_desc
.OutputWindow
, expected_client_rect
);
2084 expected_width
= expected_client_rect
->right
;
2085 expected_height
= expected_client_rect
->bottom
;
2087 creation_desc
.BufferDesc
.Width
= 0;
2088 creation_desc
.BufferDesc
.Height
= 0;
2089 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2090 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2091 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2092 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2093 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2094 result_desc
.BufferDesc
.Width
, expected_width
);
2095 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2096 result_desc
.BufferDesc
.Height
, expected_height
);
2097 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2098 IDXGISwapChain_Release(swapchain
);
2100 DestroyWindow(creation_desc
.OutputWindow
);
2101 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2102 WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
2103 1, 1, 0, 0, 0, 0, 0, 0);
2104 expected_state
.fullscreen_state
.style
= WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
2105 expected_state
.fullscreen_state
.exstyle
= 0;
2106 SetRect(&expected_state
.fullscreen_state
.window_rect
, 1, 1, 1, 1);
2107 SetRectEmpty(expected_client_rect
);
2108 expected_width
= expected_height
= 8;
2110 creation_desc
.BufferDesc
.Width
= 0;
2111 creation_desc
.BufferDesc
.Height
= 0;
2112 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2113 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2114 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2115 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2116 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2117 result_desc
.BufferDesc
.Width
, expected_width
);
2118 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2119 result_desc
.BufferDesc
.Height
, expected_height
);
2120 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2121 IDXGISwapChain_Release(swapchain
);
2123 DestroyWindow(creation_desc
.OutputWindow
);
2124 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
2125 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2128 creation_desc
.Windowed
= FALSE
;
2129 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2130 ok(SUCCEEDED(hr
), "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 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2134 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2135 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2136 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2137 "Failed to get containing output, hr %#x.\n", hr
);
2138 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2139 IDXGISwapChain_Release(swapchain
);
2140 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2142 win_skip("GetContainingOutput() not supported.\n");
2145 if (result_desc
.Windowed
)
2147 win_skip("Fullscreen not supported.\n");
2148 IDXGIOutput_Release(expected_state
.target
);
2152 creation_desc
.BufferDesc
.Width
= 0;
2153 creation_desc
.BufferDesc
.Height
= 0;
2154 creation_desc
.Windowed
= FALSE
;
2155 creation_desc
.Flags
= 0;
2156 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2157 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2158 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2159 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2161 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2162 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2163 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2164 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2165 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2166 result_desc
.BufferDesc
.Width
, expected_width
);
2167 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2168 result_desc
.BufferDesc
.Height
, expected_height
);
2169 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2170 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2171 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2172 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2173 IDXGISwapChain_Release(swapchain
);
2175 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
2176 creation_desc
.BufferDesc
.Width
= 0;
2177 creation_desc
.BufferDesc
.Height
= 0;
2178 creation_desc
.Windowed
= FALSE
;
2179 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2180 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2181 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2182 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2183 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2185 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2186 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
2187 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2188 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x.\n", hr
);
2189 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2190 result_desc
.BufferDesc
.Width
, expected_width
);
2191 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2192 result_desc
.BufferDesc
.Height
, expected_height
);
2193 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2194 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2195 ok(hr
== S_OK
, "Failed to set fullscreen state, hr %#x.\n", hr
);
2196 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2197 IDXGISwapChain_Release(swapchain
);
2199 IDXGIOutput_Release(expected_state
.target
);
2202 IUnknown_Release(obj
);
2203 refcount
= IDXGIDevice_Release(device
);
2204 ok(!refcount
, "Device has %u references left.\n", refcount
);
2205 refcount
= IDXGIAdapter_Release(adapter
);
2206 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
2207 refcount
= IDXGIFactory_Release(factory
);
2208 ok(!refcount
, "Factory has %u references left.\n", refcount
);
2209 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2210 DestroyWindow(creation_desc
.OutputWindow
);
2213 static void test_get_containing_output(IUnknown
*device
, BOOL is_d3d12
)
2215 unsigned int adapter_idx
, output_idx
, output_count
;
2216 DXGI_OUTPUT_DESC output_desc
, output_desc2
;
2217 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2218 IDXGIOutput
*output
, *output2
;
2219 MONITORINFOEXW monitor_info
;
2220 IDXGISwapChain
*swapchain
;
2221 IDXGIFactory
*factory
;
2222 IDXGIAdapter
*adapter
;
2223 POINT points
[4 * 16];
2231 adapter
= get_adapter(device
, is_d3d12
);
2234 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
2239 while ((hr
= IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
)) != DXGI_ERROR_NOT_FOUND
)
2241 ok(SUCCEEDED(hr
), "Failed to enumerate output %u, hr %#x.\n", output_count
, hr
);
2242 IDXGIOutput_Release(output
);
2245 IDXGIAdapter_Release(adapter
);
2247 swapchain_desc
.BufferDesc
.Width
= 100;
2248 swapchain_desc
.BufferDesc
.Height
= 100;
2249 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2250 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2251 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2252 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2253 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2254 swapchain_desc
.SampleDesc
.Count
= 1;
2255 swapchain_desc
.SampleDesc
.Quality
= 0;
2256 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2257 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2258 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2259 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 0, 0, 100, 100, 0, 0, 0, 0);
2260 swapchain_desc
.Windowed
= TRUE
;
2261 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2262 swapchain_desc
.Flags
= 0;
2264 get_factory(device
, is_d3d12
, &factory
);
2265 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2266 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2268 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, 0);
2269 ok(!!monitor
, "MonitorFromWindow failed.\n");
2271 monitor_info
.cbSize
= sizeof(monitor_info
);
2272 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2273 ok(ret
, "Failed to get monitor info.\n");
2275 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2276 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2277 "GetContainingOutput failed, hr %#x.\n", hr
);
2278 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2280 win_skip("GetContainingOutput() not supported.\n");
2284 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2285 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2287 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2288 ok(SUCCEEDED(hr
), "GetContainingOutput failed, hr %#x.\n", hr
);
2289 ok(output
!= output2
, "Got unexpected output pointers %p, %p.\n", output
, output2
);
2290 check_output_equal(output
, output2
);
2292 refcount
= IDXGIOutput_Release(output
);
2293 ok(!refcount
, "IDXGIOutput has %u references left.\n", refcount
);
2294 refcount
= IDXGIOutput_Release(output2
);
2295 ok(!refcount
, "IDXGIOutput has %u references left.\n", refcount
);
2297 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2298 "Got unexpected device name %s, expected %s.\n",
2299 wine_dbgstr_w(output_desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
2300 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2301 "Got unexpected desktop coordinates %s, expected %s.\n",
2302 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2303 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2305 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2308 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2311 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2312 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2315 /* Move the OutputWindow to the current output. */
2316 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2317 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2318 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2320 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2323 win_skip("Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2324 adapter_idx
, output_idx
, hr
);
2325 IDXGIOutput_Release(output
);
2329 check_output_equal(output
, output2
);
2331 refcount
= IDXGIOutput_Release(output2
);
2332 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
2333 adapter_idx
, output_idx
, refcount
);
2335 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
2336 for (i
= 0; i
< 4; ++i
)
2338 static const POINT offsets
[] =
2341 {-49, 0}, {-50, 0}, {-51, 0},
2342 { 0, -49}, { 0, -50}, { 0, -51},
2343 {-49, -49}, {-50, -49}, {-51, -49},
2344 {-49, -50}, {-50, -50}, {-51, -50},
2345 {-49, -51}, {-50, -51}, {-51, -51},
2347 unsigned int x
= 0, y
= 0;
2352 x
= output_desc
.DesktopCoordinates
.left
;
2353 y
= output_desc
.DesktopCoordinates
.top
;
2356 x
= output_desc
.DesktopCoordinates
.right
;
2357 y
= output_desc
.DesktopCoordinates
.top
;
2360 x
= output_desc
.DesktopCoordinates
.right
;
2361 y
= output_desc
.DesktopCoordinates
.bottom
;
2364 x
= output_desc
.DesktopCoordinates
.left
;
2365 y
= output_desc
.DesktopCoordinates
.bottom
;
2369 for (j
= 0; j
< ARRAY_SIZE(offsets
); ++j
)
2371 unsigned int idx
= ARRAY_SIZE(offsets
) * i
+ j
;
2372 assert(idx
< ARRAY_SIZE(points
));
2373 points
[idx
].x
= x
+ offsets
[j
].x
;
2374 points
[idx
].y
= y
+ offsets
[j
].y
;
2378 for (i
= 0; i
< ARRAY_SIZE(points
); ++i
)
2380 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, points
[i
].x
, points
[i
].y
,
2381 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2382 ok(ret
, "Adapter %u output %u point %u: Failed to set window position.\n",
2383 adapter_idx
, output_idx
, i
);
2385 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, MONITOR_DEFAULTTONEAREST
);
2386 ok(!!monitor
, "Adapter %u output %u point %u: Failed to get monitor from window.\n",
2387 adapter_idx
, output_idx
, i
);
2389 monitor_info
.cbSize
= sizeof(monitor_info
);
2390 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2391 ok(ret
, "Adapter %u output %u point %u: Failed to get monitor info.\n", adapter_idx
,
2394 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2395 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
),
2396 "Adapter %u output %u point %u: Failed to get containing output, hr %#x.\n",
2397 adapter_idx
, output_idx
, i
, hr
);
2400 ok(!!output2
, "Adapter %u output %u point %u: Got unexpected containing output %p.\n",
2401 adapter_idx
, output_idx
, i
, output2
);
2402 hr
= IDXGIOutput_GetDesc(output2
, &output_desc
);
2403 ok(hr
== S_OK
, "Adapter %u output %u point %u: Failed to get output desc, hr %#x.\n",
2404 adapter_idx
, output_idx
, i
, hr
);
2405 refcount
= IDXGIOutput_Release(output2
);
2406 ok(!refcount
, "Adapter %u output %u point %u: IDXGIOutput has %u references left.\n",
2407 adapter_idx
, output_idx
, i
, refcount
);
2409 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2410 "Adapter %u output %u point %u: Got unexpected device name %s, expected %s.\n",
2411 adapter_idx
, output_idx
, i
, wine_dbgstr_w(output_desc
.DeviceName
),
2412 wine_dbgstr_w(monitor_info
.szDevice
));
2413 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2414 "Adapter %u output %u point %u: Expect desktop coordinates %s, got %s.\n",
2415 adapter_idx
, output_idx
, i
,
2416 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2417 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2419 IDXGIOutput_Release(output
);
2421 IDXGIAdapter_Release(adapter
);
2424 /* Test GetContainingOutput with a full screen swapchain. The containing output should stay
2425 * the same even if the device window is moved */
2426 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2429 skip("SetFullscreenState failed, hr %#x.\n", hr
);
2433 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2436 win_skip("GetContainingOutput failed, hr %#x.\n", hr
);
2437 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2441 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2444 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2447 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2448 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2450 IDXGIOutput_Release(output
);
2452 /* Move the OutputWindow to the current output. */
2453 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2454 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2455 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2457 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2458 ok(hr
== S_OK
, "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2459 adapter_idx
, output_idx
, hr
);
2460 ok(fullscreen
, "Adapter %u output %u: Expect swapchain full screen.\n", adapter_idx
,
2462 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2463 adapter_idx
, output_idx
, output2
, output
);
2464 IDXGIOutput_Release(output
);
2466 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2467 ok(hr
== S_OK
, "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2468 adapter_idx
, output_idx
, hr
);
2469 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2470 adapter_idx
, output_idx
, output2
, output
);
2471 IDXGIOutput_Release(output
);
2473 IDXGIAdapter_Release(adapter
);
2476 IDXGIOutput_Release(output2
);
2477 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2478 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
2480 /* Test GetContainingOutput after a full screen swapchain is made windowed by pressing
2481 * Alt+Enter, then move it to another output and use Alt+Enter to enter full screen */
2484 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2487 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
,
2488 output
? &output2
: &output
)); ++output_idx
)
2494 IDXGIAdapter_Release(adapter
);
2499 if (output
&& output2
)
2501 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2502 IDXGIOutput_Release(output
);
2505 skip("SetFullscreenState failed, hr %#x.\n", hr
);
2506 IDXGIOutput_Release(output2
);
2510 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to leave full screen on the first output */
2511 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2512 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2514 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2515 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
2516 ok(!fullscreen
, "Expect swapchain not full screen.\n");
2518 /* Move the swapchain output window to the second output */
2519 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2520 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2521 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc2
.DesktopCoordinates
.left
,
2522 output_desc2
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2523 ok(ret
, "SetWindowPos failed.\n");
2525 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to enter full screen on the second output */
2526 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2527 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2530 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2531 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
2532 ok(fullscreen
, "Expect swapchain full screen.\n");
2533 ok(!!output
, "Expect output not NULL.\n");
2534 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2535 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2536 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2537 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2538 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2539 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2540 wine_dbgstr_w(output_desc
.DeviceName
));
2541 IDXGIOutput_Release(output
);
2544 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2545 ok(hr
== S_OK
, "GetContainingOutput failed, hr %#x.\n", hr
);
2546 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2547 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2548 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2549 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
2550 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2551 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2552 wine_dbgstr_w(output_desc
.DeviceName
));
2554 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2555 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
2559 skip("This test requires two outputs.\n");
2563 IDXGIOutput_Release(output
);
2565 IDXGIOutput_Release(output2
);
2568 refcount
= IDXGISwapChain_Release(swapchain
);
2569 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2570 refcount
= IDXGIFactory_Release(factory
);
2571 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
2572 DestroyWindow(swapchain_desc
.OutputWindow
);
2575 static void test_swapchain_fullscreen_state(IDXGISwapChain
*swapchain
,
2576 IDXGIAdapter
*adapter
, const struct swapchain_fullscreen_state
*initial_state
)
2578 MONITORINFOEXW monitor_info
, *output_monitor_info
;
2579 struct swapchain_fullscreen_state expected_state
;
2580 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2581 DXGI_OUTPUT_DESC output_desc
;
2582 unsigned int i
, output_count
;
2583 IDXGIOutput
*output
;
2587 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
2588 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2590 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2592 expected_state
= *initial_state
;
2593 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2594 &swapchain_desc
, &initial_state
->fullscreen_state
.monitor_rect
, 800, 600, NULL
);
2595 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2596 ok(SUCCEEDED(hr
), "GetContainingOutput failed, hr %#x.\n", hr
);
2598 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2599 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2602 skip("Could not change fullscreen state.\n");
2603 IDXGIOutput_Release(expected_state
.target
);
2606 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2608 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2609 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2610 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2612 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2613 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
2614 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2616 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2617 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2618 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2620 IDXGIOutput_Release(expected_state
.target
);
2621 expected_state
.target
= NULL
;
2624 while (IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
) != DXGI_ERROR_NOT_FOUND
)
2626 IDXGIOutput_Release(output
);
2630 output_monitor_info
= heap_calloc(output_count
, sizeof(*output_monitor_info
));
2631 ok(!!output_monitor_info
, "Failed to allocate memory.\n");
2632 for (i
= 0; i
< output_count
; ++i
)
2634 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2635 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2637 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2638 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2640 output_monitor_info
[i
].cbSize
= sizeof(*output_monitor_info
);
2641 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&output_monitor_info
[i
]);
2642 ok(ret
, "Failed to get monitor info.\n");
2644 IDXGIOutput_Release(output
);
2647 for (i
= 0; i
< output_count
; ++i
)
2649 RECT orig_monitor_rect
= output_monitor_info
[i
].rcMonitor
;
2650 IDXGIOutput
*target
;
2653 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2654 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2655 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2656 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2658 expected_state
= *initial_state
;
2659 expected_state
.target
= output
;
2660 expected_state
.fullscreen_state
.monitor
= output_desc
.Monitor
;
2661 expected_state
.fullscreen_state
.monitor_rect
= orig_monitor_rect
;
2662 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2663 &swapchain_desc
, &orig_monitor_rect
, 800, 600, NULL
);
2665 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2666 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2667 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2670 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2671 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2672 ok(target
== output
, "Got target pointer %p, expected %p.\n", target
, output
);
2673 IDXGIOutput_Release(target
);
2675 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2676 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2677 ok(fullscreen
, "Got unexpected fullscreen %#x.\n", hr
);
2679 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2680 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2681 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2682 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, output
);
2683 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
2684 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2685 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2686 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2687 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2690 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2691 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
2692 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", hr
);
2694 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2695 monitor_info
.cbSize
= sizeof(monitor_info
);
2696 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2697 ok(ret
, "Failed to get monitor info.\n");
2698 ok(EqualRect(&monitor_info
.rcMonitor
, &orig_monitor_rect
), "Got monitor rect %s, expected %s.\n",
2699 wine_dbgstr_rect(&monitor_info
.rcMonitor
), wine_dbgstr_rect(&orig_monitor_rect
));
2701 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2702 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2704 IDXGIOutput_Release(output
);
2707 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2708 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2709 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2711 for (i
= 0; i
< output_count
; ++i
)
2713 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2714 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2716 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2717 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
2719 monitor_info
.cbSize
= sizeof(monitor_info
);
2720 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2721 ok(ret
, "Failed to get monitor info.\n");
2723 ok(EqualRect(&monitor_info
.rcMonitor
, &output_monitor_info
[i
].rcMonitor
),
2724 "Got monitor rect %s, expected %s.\n",
2725 wine_dbgstr_rect(&monitor_info
.rcMonitor
),
2726 wine_dbgstr_rect(&output_monitor_info
[i
].rcMonitor
));
2728 IDXGIOutput_Release(output
);
2731 heap_free(output_monitor_info
);
2734 static void test_set_fullscreen(IUnknown
*device
, BOOL is_d3d12
)
2736 struct swapchain_fullscreen_state initial_state
;
2737 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2738 IDXGIAdapter
*adapter
= NULL
;
2739 IDXGISwapChain
*swapchain
;
2740 IDXGIFactory
*factory
;
2741 IDXGIOutput
*output
;
2746 get_factory(device
, is_d3d12
, &factory
);
2748 swapchain_desc
.BufferDesc
.Width
= 800;
2749 swapchain_desc
.BufferDesc
.Height
= 600;
2750 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2751 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2752 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2753 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2754 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2755 swapchain_desc
.SampleDesc
.Count
= 1;
2756 swapchain_desc
.SampleDesc
.Quality
= 0;
2757 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2758 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2759 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2760 swapchain_desc
.Windowed
= TRUE
;
2761 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2762 swapchain_desc
.Flags
= 0;
2764 memset(&initial_state
, 0, sizeof(initial_state
));
2765 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
2766 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2767 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2768 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2769 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2770 "Failed to get containing output, hr %#x.\n", hr
);
2773 skip("Could not get output.\n");
2776 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&adapter
);
2777 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
2778 IDXGIOutput_Release(output
);
2780 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2781 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2782 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
2783 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2784 "SetFullscreenState failed, hr %#x.\n", hr
);
2787 skip("Could not change fullscreen state.\n");
2790 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2791 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2792 refcount
= IDXGISwapChain_Release(swapchain
);
2793 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2795 DestroyWindow(swapchain_desc
.OutputWindow
);
2796 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2797 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2798 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2799 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2800 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2801 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2802 refcount
= IDXGISwapChain_Release(swapchain
);
2803 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2805 DestroyWindow(swapchain_desc
.OutputWindow
);
2806 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2807 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2808 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2809 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2810 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2811 ok(hr
== S_OK
, "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 DestroyWindow(swapchain_desc
.OutputWindow
);
2816 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2817 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2818 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2819 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2820 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2821 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2822 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2823 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2824 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2825 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2826 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2827 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2828 refcount
= IDXGISwapChain_Release(swapchain
);
2829 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2831 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2832 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2833 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2834 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2835 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, 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 DestroyWindow(swapchain_desc
.OutputWindow
);
2841 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2842 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2843 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2844 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2845 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2846 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2847 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2848 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2849 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2850 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2851 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2852 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
2853 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2854 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2855 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2856 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2857 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
2858 refcount
= IDXGISwapChain_Release(swapchain
);
2859 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2861 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2862 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2863 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2864 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2865 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
2866 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2867 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2871 IDXGIAdapter_Release(adapter
);
2872 refcount
= IDXGISwapChain_Release(swapchain
);
2873 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
2874 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2875 DestroyWindow(swapchain_desc
.OutputWindow
);
2877 refcount
= IDXGIFactory_Release(factory
);
2878 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
2881 static void test_default_fullscreen_target_output(IUnknown
*device
, BOOL is_d3d12
)
2883 IDXGIOutput
*output
, *containing_output
, *target
;
2884 unsigned int adapter_idx
, output_idx
;
2885 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2886 DXGI_OUTPUT_DESC output_desc
;
2887 unsigned int width
, height
;
2888 IDXGISwapChain
*swapchain
;
2889 IDXGIFactory
*factory
;
2890 IDXGIAdapter
*adapter
;
2891 BOOL fullscreen
, ret
;
2896 get_factory(device
, is_d3d12
, &factory
);
2898 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2899 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2900 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2901 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2902 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2903 swapchain_desc
.SampleDesc
.Count
= 1;
2904 swapchain_desc
.SampleDesc
.Quality
= 0;
2905 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2906 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2907 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2908 swapchain_desc
.Flags
= 0;
2910 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2913 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2916 /* Windowed swapchain */
2917 swapchain_desc
.BufferDesc
.Width
= 640;
2918 swapchain_desc
.BufferDesc
.Height
= 480;
2919 swapchain_desc
.OutputWindow
= create_window();
2920 swapchain_desc
.Windowed
= TRUE
;
2921 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2922 ok(SUCCEEDED(hr
), "Adapter %u output %u: CreateSwapChain failed, hr %#x.\n",
2923 adapter_idx
, output_idx
, hr
);
2925 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
2926 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2927 adapter_idx
, output_idx
, hr
);
2928 ok(!fullscreen
, "Adapter %u output %u: Expected not fullscreen.\n", adapter_idx
,
2930 ok(!containing_output
, "Adapter %u output %u: Expected a null output.\n", adapter_idx
,
2933 /* Move the OutputWindow to the current output. */
2934 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2935 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
2937 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0,
2938 output_desc
.DesktopCoordinates
.left
, output_desc
.DesktopCoordinates
.top
,
2939 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2940 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#x.\n", adapter_idx
,
2941 output_idx
, GetLastError());
2943 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2944 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2945 "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n", adapter_idx
,
2947 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2949 win_skip("Adapter %u output %u: GetContainingOutput() not supported.\n",
2950 adapter_idx
, output_idx
);
2951 IDXGISwapChain_Release(swapchain
);
2952 IDXGIOutput_Release(output
);
2953 DestroyWindow(swapchain_desc
.OutputWindow
);
2957 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2958 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
2959 "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n", adapter_idx
,
2961 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
2963 skip("Adapter %u output %u: Could not change fullscreen state.\n", adapter_idx
,
2965 IDXGIOutput_Release(containing_output
);
2966 IDXGISwapChain_Release(swapchain
);
2967 IDXGIOutput_Release(output
);
2968 DestroyWindow(swapchain_desc
.OutputWindow
);
2971 GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
2972 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
2973 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
2974 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2975 wine_dbgstr_rect(&window_rect
));
2978 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2979 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
2980 adapter_idx
, output_idx
, hr
);
2981 ok(target
!= containing_output
,
2982 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
2983 output_idx
, target
, containing_output
);
2984 check_output_equal(target
, containing_output
);
2986 refcount
= IDXGIOutput_Release(containing_output
);
2987 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
2988 adapter_idx
, output_idx
, refcount
);
2990 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2991 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
2992 adapter_idx
, output_idx
, hr
);
2993 ok(containing_output
== target
,
2994 "Adapter %u output %u: Got unexpected containing output %p, expected %p.\n",
2995 adapter_idx
, output_idx
, containing_output
, target
);
2996 refcount
= IDXGIOutput_Release(containing_output
);
2997 ok(refcount
>= 2, "Adapter %u output %u: Got unexpected refcount %u.\n", adapter_idx
,
2998 output_idx
, refcount
);
2999 refcount
= IDXGIOutput_Release(target
);
3000 ok(refcount
>= 1, "Adapter %u output %u: Got unexpected refcount %u.\n", adapter_idx
,
3001 output_idx
, refcount
);
3003 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3004 ok(SUCCEEDED(hr
), "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n",
3005 adapter_idx
, output_idx
, hr
);
3006 refcount
= IDXGISwapChain_Release(swapchain
);
3007 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
3008 adapter_idx
, output_idx
, refcount
);
3009 DestroyWindow(swapchain_desc
.OutputWindow
);
3011 /* Full screen swapchain */
3012 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
3013 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
3014 swapchain_desc
.BufferDesc
.Width
= width
;
3015 swapchain_desc
.BufferDesc
.Height
= height
;
3016 swapchain_desc
.OutputWindow
= create_window();
3017 swapchain_desc
.Windowed
= FALSE
;
3018 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
3019 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
3020 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#x.\n", adapter_idx
,
3021 output_idx
, GetLastError());
3022 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3025 skip("Adapter %u output %u: CreateSwapChain failed, hr %#x.\n", adapter_idx
,
3027 IDXGIOutput_Release(output
);
3028 DestroyWindow(swapchain_desc
.OutputWindow
);
3032 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
3033 ok(SUCCEEDED(hr
), "Adapter %u output %u: GetFullscreenState failed, hr %#x.\n",
3034 adapter_idx
, output_idx
, hr
);
3035 ok(fullscreen
, "Adapter %u output %u: Expected fullscreen.\n", adapter_idx
, output_idx
);
3036 ok(!!containing_output
, "Adapter %u output %u: Expected a valid output.\n", adapter_idx
,
3038 if (containing_output
)
3039 IDXGIOutput_Release(containing_output
);
3041 ret
= GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
3042 ok(ret
, "Adapter %u output %u: GetWindowRect failed, error %#x.\n", adapter_idx
,
3043 output_idx
, GetLastError());
3044 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
3045 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
3046 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3047 wine_dbgstr_rect(&window_rect
));
3049 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
3050 ok(hr
== S_OK
, "Adapter %u output %u: GetContainingOutput failed, hr %#x.\n",
3051 adapter_idx
, output_idx
, hr
);
3052 ok(containing_output
!= output
,
3053 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
3054 output_idx
, output
, containing_output
);
3055 check_output_equal(output
, containing_output
);
3056 IDXGIOutput_Release(containing_output
);
3058 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3059 ok(hr
== S_OK
, "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n",
3060 adapter_idx
, output_idx
, hr
);
3061 refcount
= IDXGISwapChain_Release(swapchain
);
3062 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
3063 adapter_idx
, output_idx
, refcount
);
3064 refcount
= IDXGIOutput_Release(output
);
3065 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
3066 adapter_idx
, output_idx
, refcount
);
3067 DestroyWindow(swapchain_desc
.OutputWindow
);
3069 IDXGIAdapter_Release(adapter
);
3072 refcount
= IDXGIFactory_Release(factory
);
3073 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
3076 static void test_windowed_resize_target(IDXGISwapChain
*swapchain
, HWND window
,
3077 struct swapchain_fullscreen_state
*state
)
3079 struct swapchain_fullscreen_state expected_state
;
3080 struct fullscreen_state
*e
;
3081 DXGI_MODE_DESC mode
;
3089 unsigned int width
, height
;
3102 check_swapchain_fullscreen_state(swapchain
, state
);
3103 expected_state
= *state
;
3104 e
= &expected_state
.fullscreen_state
;
3106 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3108 SetRect(&e
->client_rect
, 0, 0, sizes
[i
].width
, sizes
[i
].height
);
3109 e
->window_rect
= e
->client_rect
;
3110 ret
= AdjustWindowRectEx(&e
->window_rect
, GetWindowLongW(window
, GWL_STYLE
),
3111 FALSE
, GetWindowLongW(window
, GWL_EXSTYLE
));
3112 ok(ret
, "AdjustWindowRectEx failed.\n");
3113 if (GetMenu(window
))
3114 e
->client_rect
.bottom
-= GetSystemMetrics(SM_CYMENU
);
3115 SetRect(&e
->window_rect
, 0, 0,
3116 e
->window_rect
.right
- e
->window_rect
.left
,
3117 e
->window_rect
.bottom
- e
->window_rect
.top
);
3118 GetWindowRect(window
, &window_rect
);
3119 OffsetRect(&e
->window_rect
, window_rect
.left
, window_rect
.top
);
3120 if (e
->window_rect
.right
>= e
->monitor_rect
.right
3121 || e
->window_rect
.bottom
>= e
->monitor_rect
.bottom
)
3123 skip("Test %u: Window %s does not fit on screen %s.\n",
3124 i
, wine_dbgstr_rect(&e
->window_rect
), wine_dbgstr_rect(&e
->monitor_rect
));
3128 memset(&mode
, 0, sizeof(mode
));
3129 mode
.Width
= sizes
[i
].width
;
3130 mode
.Height
= sizes
[i
].height
;
3131 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3132 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3133 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3136 ret
= SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOZORDER
);
3137 ok(ret
, "SetWindowPos failed, error %#x.\n", GetLastError());
3138 GetWindowRect(window
, &e
->window_rect
);
3139 GetClientRect(window
, &e
->client_rect
);
3140 ret
= SetWindowPos(window
, 0, 0, 0, 200, 200, SWP_NOMOVE
| SWP_NOZORDER
);
3141 ok(ret
, "SetWindowPos failed, error %#x.\n", GetLastError());
3143 memset(&mode
, 0, sizeof(mode
));
3144 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3145 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3146 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3148 GetWindowRect(window
, &e
->window_rect
);
3149 GetClientRect(window
, &e
->client_rect
);
3150 *state
= expected_state
;
3153 static void test_fullscreen_resize_target(IDXGISwapChain
*swapchain
,
3154 const struct swapchain_fullscreen_state
*initial_state
)
3156 struct swapchain_fullscreen_state expected_state
;
3157 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3158 DXGI_OUTPUT_DESC output_desc
;
3159 unsigned int i
, mode_count
;
3160 DXGI_MODE_DESC
*modes
;
3161 IDXGIOutput
*target
;
3164 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3165 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3167 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
3168 ok(SUCCEEDED(hr
), "GetFullscreenState failed, hr %#x.\n", hr
);
3170 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
3171 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
3172 "Failed to list modes, hr %#x.\n", hr
);
3173 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3175 win_skip("GetDisplayModeList() not supported.\n");
3176 IDXGIOutput_Release(target
);
3180 modes
= heap_calloc(mode_count
, sizeof(*modes
));
3181 ok(!!modes
, "Failed to allocate memory.\n");
3183 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
3184 ok(SUCCEEDED(hr
), "Failed to list modes, hr %#x.\n", hr
);
3186 expected_state
= *initial_state
;
3187 for (i
= 0; i
< min(mode_count
, 20); ++i
)
3189 /* FIXME: Modes with scaling aren't fully tested. */
3190 if (!(swapchain_desc
.Flags
& DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
)
3191 && modes
[i
].Scaling
!= DXGI_MODE_SCALING_UNSPECIFIED
)
3194 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3195 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3197 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3198 &swapchain_desc
, &output_desc
.DesktopCoordinates
, modes
[i
].Width
, modes
[i
].Height
, NULL
);
3200 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &modes
[i
]);
3201 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#x.\n", hr
);
3202 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3204 skip("Failed to change to video mode %u.\n", i
);
3207 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3209 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3210 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3211 ok(EqualRect(&output_desc
.DesktopCoordinates
, &expected_state
.fullscreen_state
.monitor_rect
),
3212 "Got desktop coordinates %s, expected %s.\n",
3213 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3214 wine_dbgstr_rect(&expected_state
.fullscreen_state
.monitor_rect
));
3218 IDXGIOutput_Release(target
);
3221 static void test_resize_target(IUnknown
*device
, BOOL is_d3d12
)
3223 struct swapchain_fullscreen_state initial_state
, expected_state
;
3224 unsigned int adapter_idx
, output_idx
, test_idx
;
3225 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3226 DXGI_OUTPUT_DESC output_desc
;
3227 IDXGISwapChain
*swapchain
;
3228 IDXGIFactory
*factory
;
3229 IDXGIAdapter
*adapter
;
3230 IDXGIOutput
*output
;
3243 {{ 0, 0}, TRUE
, FALSE
, 0},
3244 {{10, 10}, TRUE
, FALSE
, 0},
3245 {{ 0, 0}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3246 {{10, 10}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3247 {{ 0, 0}, FALSE
, FALSE
, 0},
3248 {{ 0, 0}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3249 {{10, 10}, FALSE
, FALSE
, 0},
3250 {{10, 10}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3251 {{ 0, 0}, FALSE
, TRUE
, 0},
3252 {{ 0, 0}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3253 {{10, 10}, FALSE
, TRUE
, 0},
3254 {{10, 10}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3257 get_factory(device
, is_d3d12
, &factory
);
3259 swapchain_desc
.BufferDesc
.Width
= 800;
3260 swapchain_desc
.BufferDesc
.Height
= 600;
3261 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3262 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3263 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3264 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3265 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3266 swapchain_desc
.SampleDesc
.Count
= 1;
3267 swapchain_desc
.SampleDesc
.Quality
= 0;
3268 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3269 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
3270 swapchain_desc
.Windowed
= TRUE
;
3271 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
3272 swapchain_desc
.Flags
= 0;
3274 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
3277 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
3280 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
3281 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
3284 for (test_idx
= 0; test_idx
< ARRAY_SIZE(tests
); ++test_idx
)
3286 swapchain_desc
.Flags
= tests
[test_idx
].flags
;
3287 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0,
3288 output_desc
.DesktopCoordinates
.left
+ tests
[test_idx
].origin
.x
,
3289 output_desc
.DesktopCoordinates
.top
+ tests
[test_idx
].origin
.y
,
3290 400, 200, 0, 0, 0, 0);
3291 if (tests
[test_idx
].menu
)
3293 HMENU menu_bar
= CreateMenu();
3294 HMENU menu
= CreateMenu();
3295 AppendMenuA(menu_bar
, MF_POPUP
, (UINT_PTR
)menu
, "Menu");
3296 SetMenu(swapchain_desc
.OutputWindow
, menu_bar
);
3299 memset(&initial_state
, 0, sizeof(initial_state
));
3300 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3302 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3303 ok(SUCCEEDED(hr
), "Adapter %u output %u test %u: CreateSwapChain failed, hr %#x.\n",
3304 adapter_idx
, output_idx
, test_idx
, hr
);
3305 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3307 expected_state
= initial_state
;
3308 if (tests
[test_idx
].fullscreen
)
3310 expected_state
.fullscreen
= TRUE
;
3311 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3312 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 800, 600, NULL
);
3313 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
3314 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3315 "Adapter %u output %u test %u: GetContainingOutput failed, hr %#x.\n",
3316 adapter_idx
, output_idx
, test_idx
, hr
);
3317 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3319 win_skip("Adapter %u output %u test %u: GetContainingOutput() not supported.\n",
3320 adapter_idx
, output_idx
, test_idx
);
3321 IDXGISwapChain_Release(swapchain
);
3322 DestroyWindow(swapchain_desc
.OutputWindow
);
3326 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
3327 ok(SUCCEEDED(hr
) || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
3328 "Adapter %u output %u test %u: SetFullscreenState failed, hr %#x.\n",
3329 adapter_idx
, output_idx
, test_idx
, hr
);
3330 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3332 skip("Adapter %u output %u test %u: Could not change fullscreen state.\n",
3333 adapter_idx
, output_idx
, test_idx
);
3334 IDXGIOutput_Release(expected_state
.target
);
3335 IDXGISwapChain_Release(swapchain
);
3336 DestroyWindow(swapchain_desc
.OutputWindow
);
3340 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3342 hr
= IDXGISwapChain_ResizeTarget(swapchain
, NULL
);
3343 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Adapter %u output %u test %u: Got unexpected hr %#x.\n",
3344 adapter_idx
, output_idx
, test_idx
, hr
);
3345 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3347 if (tests
[test_idx
].fullscreen
)
3349 test_fullscreen_resize_target(swapchain
, &expected_state
);
3351 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3352 ok(SUCCEEDED(hr
), "Adapter %u output %u test %u: SetFullscreenState failed, hr %#x.\n",
3353 adapter_idx
, output_idx
, test_idx
, hr
);
3354 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3355 IDXGIOutput_Release(expected_state
.target
);
3356 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3357 expected_state
= initial_state
;
3361 test_windowed_resize_target(swapchain
, swapchain_desc
.OutputWindow
, &expected_state
);
3363 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3366 refcount
= IDXGISwapChain_Release(swapchain
);
3367 ok(!refcount
, "Adapter %u output %u test %u: IDXGISwapChain has %u references left.\n",
3368 adapter_idx
, output_idx
, test_idx
, refcount
);
3369 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &expected_state
.fullscreen_state
);
3370 DestroyWindow(swapchain_desc
.OutputWindow
);
3372 IDXGIOutput_Release(output
);
3374 IDXGIAdapter_Release(adapter
);
3376 refcount
= IDXGIFactory_Release(factory
);
3377 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
3380 static LRESULT CALLBACK
resize_target_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
3382 IDXGISwapChain
*swapchain
= (IDXGISwapChain
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
3383 DXGI_SWAP_CHAIN_DESC desc
;
3389 ok(!!swapchain
, "GWLP_USERDATA is NULL.\n");
3390 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
3391 ok(hr
== S_OK
, "Failed to get desc, hr %#x.\n", hr
);
3392 ok(desc
.BufferDesc
.Width
== 800, "Got unexpected buffer width %u.\n", desc
.BufferDesc
.Width
);
3393 ok(desc
.BufferDesc
.Height
== 600, "Got unexpected buffer height %u.\n", desc
.BufferDesc
.Height
);
3397 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
3401 struct window_thread_data
3404 HANDLE window_created
;
3408 static DWORD WINAPI
window_thread(void *data
)
3410 struct window_thread_data
*thread_data
= data
;
3415 memset(&wc
, 0, sizeof(wc
));
3416 wc
.lpfnWndProc
= resize_target_wndproc
;
3417 wc
.lpszClassName
= "dxgi_resize_target_wndproc_wc";
3418 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
3420 thread_data
->window
= CreateWindowA("dxgi_resize_target_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3421 ok(!!thread_data
->window
, "Failed to create window.\n");
3423 ret
= SetEvent(thread_data
->window_created
);
3424 ok(ret
, "Failed to set event, last error %#x.\n", GetLastError());
3428 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3429 DispatchMessageA(&msg
);
3431 ret
= WaitForSingleObject(thread_data
->finished
, 0);
3432 if (ret
!= WAIT_TIMEOUT
)
3435 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for event, ret %#x, last error %#x.\n", ret
, GetLastError());
3437 DestroyWindow(thread_data
->window
);
3438 thread_data
->window
= NULL
;
3440 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
3445 static void test_resize_target_wndproc(void)
3447 struct window_thread_data thread_data
;
3448 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3449 IDXGISwapChain
*swapchain
;
3450 IDXGIFactory
*factory
;
3451 IDXGIAdapter
*adapter
;
3452 DXGI_MODE_DESC mode
;
3453 IDXGIDevice
*device
;
3461 if (!(device
= create_device(0)))
3463 skip("Failed to create device.\n");
3467 memset(&thread_data
, 0, sizeof(thread_data
));
3468 thread_data
.window_created
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3469 ok(!!thread_data
.window_created
, "Failed to create event, last error %#x.\n", GetLastError());
3470 thread_data
.finished
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3471 ok(!!thread_data
.finished
, "Failed to create event, last error %#x.\n", GetLastError());
3473 thread
= CreateThread(NULL
, 0, window_thread
, &thread_data
, 0, NULL
);
3474 ok(!!thread
, "Failed to create thread, last error %#x.\n", GetLastError());
3475 ret
= WaitForSingleObject(thread_data
.window_created
, INFINITE
);
3476 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#x.\n", ret
, GetLastError());
3478 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3479 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
3480 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3481 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
3483 swapchain_desc
.BufferDesc
.Width
= 800;
3484 swapchain_desc
.BufferDesc
.Height
= 600;
3485 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3486 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3487 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3488 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3489 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3490 swapchain_desc
.SampleDesc
.Count
= 1;
3491 swapchain_desc
.SampleDesc
.Quality
= 0;
3492 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3493 swapchain_desc
.BufferCount
= 1;
3494 swapchain_desc
.OutputWindow
= thread_data
.window
;
3495 swapchain_desc
.Windowed
= TRUE
;
3496 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3497 swapchain_desc
.Flags
= 0;
3498 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3499 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
3501 data
= SetWindowLongPtrA(thread_data
.window
, GWLP_USERDATA
, (LONG_PTR
)swapchain
);
3502 ok(!data
, "Got unexpected GWLP_USERDATA %p.\n", (void *)data
);
3504 memset(&mode
, 0, sizeof(mode
));
3507 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3508 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3510 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3511 ok(hr
== S_OK
, "Getswapchain_desc failed, hr %#x.\n", hr
);
3512 ok(swapchain_desc
.BufferDesc
.Width
== 800,
3513 "Got unexpected buffer width %u.\n", swapchain_desc
.BufferDesc
.Width
);
3514 ok(swapchain_desc
.BufferDesc
.Height
== 600,
3515 "Got unexpected buffer height %u.\n", swapchain_desc
.BufferDesc
.Height
);
3517 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
3518 ok(ret
, "Failed to get client rect.\n");
3519 ok(rect
.right
== mode
.Width
&& rect
.bottom
== mode
.Height
,
3520 "Got unexpected client rect %s.\n", wine_dbgstr_rect(&rect
));
3522 refcount
= IDXGISwapChain_Release(swapchain
);
3523 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3525 IDXGIAdapter_Release(adapter
);
3526 refcount
= IDXGIDevice_Release(device
);
3527 ok(!refcount
, "Device has %u references left.\n", refcount
);
3528 refcount
= IDXGIFactory_Release(factory
);
3529 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3531 ret
= SetEvent(thread_data
.finished
);
3532 ok(ret
, "Failed to set event, last error %#x.\n", GetLastError());
3533 ret
= WaitForSingleObject(thread
, INFINITE
);
3534 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#x.\n", ret
, GetLastError());
3535 CloseHandle(thread
);
3536 CloseHandle(thread_data
.window_created
);
3537 CloseHandle(thread_data
.finished
);
3540 static void test_inexact_modes(void)
3542 struct swapchain_fullscreen_state initial_state
, expected_state
;
3543 DXGI_SWAP_CHAIN_DESC swapchain_desc
, result_desc
;
3544 IDXGIOutput
*output
= NULL
;
3545 IDXGISwapChain
*swapchain
;
3546 IDXGIFactory
*factory
;
3547 IDXGIAdapter
*adapter
;
3548 IDXGIDevice
*device
;
3555 unsigned int width
, height
;
3564 if (!(device
= create_device(0)))
3566 skip("Failed to create device.\n");
3570 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3571 ok(SUCCEEDED(hr
), "GetAdapter failed, hr %#x.\n", hr
);
3573 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3574 ok(SUCCEEDED(hr
), "GetParent failed, hr %#x.\n", hr
);
3576 swapchain_desc
.BufferDesc
.Width
= 800;
3577 swapchain_desc
.BufferDesc
.Height
= 600;
3578 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3579 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3580 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3581 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3582 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3583 swapchain_desc
.SampleDesc
.Count
= 1;
3584 swapchain_desc
.SampleDesc
.Quality
= 0;
3585 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3586 swapchain_desc
.BufferCount
= 1;
3587 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3588 swapchain_desc
.Windowed
= FALSE
;
3589 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3590 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
3592 memset(&initial_state
, 0, sizeof(initial_state
));
3593 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3595 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3596 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3597 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3598 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3599 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3600 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3601 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
3602 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3603 "GetContainingOutput failed, hr %#x.\n", hr
);
3604 refcount
= IDXGISwapChain_Release(swapchain
);
3605 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3606 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3608 win_skip("GetContainingOutput() not supported.\n");
3611 if (result_desc
.Windowed
)
3613 win_skip("Fullscreen not supported.\n");
3617 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
3619 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3621 /* Test CreateSwapChain(). */
3622 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3623 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3624 swapchain_desc
.Windowed
= FALSE
;
3626 expected_state
= initial_state
;
3627 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3628 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
,
3629 sizes
[i
].width
, sizes
[i
].height
, output
);
3631 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3632 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3634 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3635 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3636 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3637 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3638 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3639 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3640 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3642 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3643 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3644 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3646 refcount
= IDXGISwapChain_Release(swapchain
);
3647 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3649 /* Test SetFullscreenState(). */
3650 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3651 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3652 swapchain_desc
.Windowed
= TRUE
;
3654 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3655 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3657 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3658 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3660 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3661 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3662 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3663 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3664 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3665 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3666 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3668 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3669 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3670 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3672 refcount
= IDXGISwapChain_Release(swapchain
);
3673 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3675 /* Test ResizeTarget(). */
3676 swapchain_desc
.BufferDesc
.Width
= 800;
3677 swapchain_desc
.BufferDesc
.Height
= 600;
3678 swapchain_desc
.Windowed
= TRUE
;
3680 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3681 ok(SUCCEEDED(hr
), "CreateSwapChain failed, hr %#x.\n", hr
);
3683 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3684 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3686 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3687 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3688 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &swapchain_desc
.BufferDesc
);
3689 ok(SUCCEEDED(hr
), "ResizeTarget failed, hr %#x.\n", hr
);
3691 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3692 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3693 ok(SUCCEEDED(hr
), "GetDesc failed, hr %#x.\n", hr
);
3694 ok(result_desc
.BufferDesc
.Width
== 800, "Got width %u.\n", result_desc
.BufferDesc
.Width
);
3695 ok(result_desc
.BufferDesc
.Height
== 600, "Got height %u.\n", result_desc
.BufferDesc
.Height
);
3697 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3698 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
3699 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3701 refcount
= IDXGISwapChain_Release(swapchain
);
3702 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
3707 IDXGIOutput_Release(output
);
3708 IDXGIAdapter_Release(adapter
);
3709 refcount
= IDXGIDevice_Release(device
);
3710 ok(!refcount
, "Device has %u references left.\n", refcount
);
3711 refcount
= IDXGIFactory_Release(factory
);
3712 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3713 DestroyWindow(swapchain_desc
.OutputWindow
);
3716 static void test_create_factory(void)
3722 iface
= (void *)0xdeadbeef;
3723 hr
= CreateDXGIFactory(&IID_IDXGIDevice
, (void **)&iface
);
3724 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3725 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3727 hr
= CreateDXGIFactory(&IID_IUnknown
, (void **)&iface
);
3728 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr
);
3729 IUnknown_Release(iface
);
3731 hr
= CreateDXGIFactory(&IID_IDXGIObject
, (void **)&iface
);
3732 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr
);
3733 IUnknown_Release(iface
);
3735 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&iface
);
3736 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr
);
3737 check_interface(iface
, &IID_IDXGIFactory1
, FALSE
, FALSE
);
3738 IUnknown_Release(iface
);
3740 iface
= (void *)0xdeadbeef;
3741 hr
= CreateDXGIFactory(&IID_IDXGIFactory1
, (void **)&iface
);
3742 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3743 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3746 hr
= CreateDXGIFactory(&IID_IDXGIFactory2
, (void **)&iface
);
3747 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3748 "Got unexpected hr %#x.\n", hr
);
3751 refcount
= IUnknown_Release(iface
);
3752 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3755 if (!pCreateDXGIFactory1
)
3757 win_skip("CreateDXGIFactory1 not available.\n");
3761 iface
= (void *)0xdeadbeef;
3762 hr
= pCreateDXGIFactory1(&IID_IDXGIDevice
, (void **)&iface
);
3763 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#x.\n", hr
);
3764 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3766 hr
= pCreateDXGIFactory1(&IID_IUnknown
, (void **)&iface
);
3767 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IUnknown, hr %#x.\n", hr
);
3768 IUnknown_Release(iface
);
3770 hr
= pCreateDXGIFactory1(&IID_IDXGIObject
, (void **)&iface
);
3771 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIObject, hr %#x.\n", hr
);
3772 IUnknown_Release(iface
);
3774 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory
, (void **)&iface
);
3775 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory, hr %#x.\n", hr
);
3776 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3777 refcount
= IUnknown_Release(iface
);
3778 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3780 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory1
, (void **)&iface
);
3781 ok(SUCCEEDED(hr
), "Failed to create factory with IID_IDXGIFactory1, hr %#x.\n", hr
);
3782 IUnknown_Release(iface
);
3785 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory2
, (void **)&iface
);
3786 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3787 "Got unexpected hr %#x.\n", hr
);
3790 refcount
= IUnknown_Release(iface
);
3791 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3794 if (!pCreateDXGIFactory2
)
3796 win_skip("CreateDXGIFactory2 not available.\n");
3800 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory3
, (void **)&iface
);
3801 ok(hr
== S_OK
, "Failed to create factory, hr %#x.\n", hr
);
3802 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3803 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3804 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3805 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3806 /* Not available on all Windows versions. */
3807 check_interface(iface
, &IID_IDXGIFactory4
, TRUE
, TRUE
);
3808 check_interface(iface
, &IID_IDXGIFactory5
, TRUE
, TRUE
);
3809 refcount
= IUnknown_Release(iface
);
3810 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3812 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory
, (void **)&iface
);
3813 ok(hr
== S_OK
, "Failed to create factory, hr %#x.\n", hr
);
3814 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3815 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3816 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3817 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3818 refcount
= IUnknown_Release(iface
);
3819 ok(!refcount
, "Factory has %u references left.\n", refcount
);
3822 static void test_private_data(void)
3824 ULONG refcount
, expected_refcount
;
3825 IDXGIDevice
*device
;
3827 IDXGIDevice
*test_object
;
3829 static const DWORD data
[] = {1, 2, 3, 4};
3831 static const GUID dxgi_private_data_test_guid
=
3836 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
3838 static const GUID dxgi_private_data_test_guid2
=
3843 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
3846 if (!(device
= create_device(0)))
3848 skip("Failed to create device.\n");
3852 test_object
= create_device(0);
3854 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
3855 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
3856 * NULL interface is not considered a clear but as setting an interface pointer that
3857 * happens to be NULL. */
3858 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 0, NULL
);
3859 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3860 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3861 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3862 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3863 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3864 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3865 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3867 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3868 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3869 size
= sizeof(ptr
) * 2;
3870 ptr
= (IUnknown
*)0xdeadbeef;
3871 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3872 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3873 ok(!ptr
, "Got unexpected pointer %p.\n", ptr
);
3874 ok(size
== sizeof(IUnknown
*), "Got unexpected size %u.\n", size
);
3876 refcount
= get_refcount(test_object
);
3877 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3878 (IUnknown
*)test_object
);
3879 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3880 expected_refcount
= refcount
+ 1;
3881 refcount
= get_refcount(test_object
);
3882 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3883 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3884 (IUnknown
*)test_object
);
3885 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3886 refcount
= get_refcount(test_object
);
3887 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3889 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3890 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3891 expected_refcount
--;
3892 refcount
= get_refcount(test_object
);
3893 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3895 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3896 (IUnknown
*)test_object
);
3897 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3898 size
= sizeof(data
);
3899 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, size
, data
);
3900 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3901 refcount
= get_refcount(test_object
);
3902 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3903 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3904 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3905 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3906 ok(hr
== S_FALSE
, "Got unexpected hr %#x.\n", hr
);
3908 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3909 (IUnknown
*)test_object
);
3910 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3911 expected_refcount
++;
3912 size
= 2 * sizeof(ptr
);
3914 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3915 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3916 ok(size
== sizeof(test_object
), "Got unexpected size %u.\n", size
);
3917 expected_refcount
++;
3918 refcount
= get_refcount(test_object
);
3919 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3921 IUnknown_Release(ptr
);
3922 expected_refcount
--;
3924 ptr
= (IUnknown
*)0xdeadbeef;
3926 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3927 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3928 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3929 size
= 2 * sizeof(ptr
);
3930 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3931 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
3932 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3933 refcount
= get_refcount(test_object
);
3934 ok(refcount
== expected_refcount
, "Got unexpected refcount %u, expected %u.\n", refcount
, expected_refcount
);
3937 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3938 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#x.\n", hr
);
3939 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3940 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3941 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, NULL
, NULL
);
3942 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
3944 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, &size
, &ptr
);
3945 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#x.\n", hr
);
3946 ok(size
== 0, "Got unexpected size %u.\n", size
);
3947 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3948 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, NULL
, &ptr
);
3949 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#x.\n", hr
);
3950 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3952 refcount
= IDXGIDevice_Release(device
);
3953 ok(!refcount
, "Device has %u references left.\n", refcount
);
3954 refcount
= IDXGIDevice_Release(test_object
);
3955 ok(!refcount
, "Test object has %u references left.\n", refcount
);
3958 #define check_surface_desc(a, b) check_surface_desc_(__LINE__, a, b)
3959 static void check_surface_desc_(unsigned int line
, IDXGISurface
*surface
,
3960 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3962 DXGI_SURFACE_DESC surface_desc
;
3965 hr
= IDXGISurface_GetDesc(surface
, &surface_desc
);
3966 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get surface desc, hr %#x.\n", hr
);
3967 ok_(__FILE__
, line
)(surface_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3968 "Got Width %u, expected %u.\n", surface_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3969 ok_(__FILE__
, line
)(surface_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3970 "Got Height %u, expected %u.\n", surface_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3971 ok_(__FILE__
, line
)(surface_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3972 "Got Format %#x, expected %#x.\n", surface_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3973 ok_(__FILE__
, line
)(surface_desc
.SampleDesc
.Count
== 1,
3974 "Got unexpected SampleDesc.Count %u.\n", surface_desc
.SampleDesc
.Count
);
3975 ok_(__FILE__
, line
)(!surface_desc
.SampleDesc
.Quality
,
3976 "Got unexpected SampleDesc.Quality %u.\n", surface_desc
.SampleDesc
.Quality
);
3979 #define check_texture_desc(a, b) check_texture_desc_(__LINE__, a, b)
3980 static void check_texture_desc_(unsigned int line
, ID3D10Texture2D
*texture
,
3981 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3983 D3D10_TEXTURE2D_DESC texture_desc
;
3985 ID3D10Texture2D_GetDesc(texture
, &texture_desc
);
3986 ok_(__FILE__
, line
)(texture_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3987 "Got Width %u, expected %u.\n", texture_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3988 ok_(__FILE__
, line
)(texture_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3989 "Got Height %u, expected %u.\n", texture_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3990 ok_(__FILE__
, line
)(texture_desc
.MipLevels
== 1, "Got unexpected MipLevels %u.\n", texture_desc
.MipLevels
);
3991 ok_(__FILE__
, line
)(texture_desc
.ArraySize
== 1, "Got unexpected ArraySize %u.\n", texture_desc
.ArraySize
);
3992 ok_(__FILE__
, line
)(texture_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3993 "Got Format %#x, expected %#x.\n", texture_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3994 ok_(__FILE__
, line
)(texture_desc
.SampleDesc
.Count
== 1,
3995 "Got unexpected SampleDesc.Count %u.\n", texture_desc
.SampleDesc
.Count
);
3996 ok_(__FILE__
, line
)(!texture_desc
.SampleDesc
.Quality
,
3997 "Got unexpected SampleDesc.Quality %u.\n", texture_desc
.SampleDesc
.Quality
);
3998 ok_(__FILE__
, line
)(texture_desc
.Usage
== D3D10_USAGE_DEFAULT
,
3999 "Got unexpected Usage %#x.\n", texture_desc
.Usage
);
4000 ok_(__FILE__
, line
)(texture_desc
.BindFlags
== D3D10_BIND_RENDER_TARGET
,
4001 "Got unexpected BindFlags %#x.\n", texture_desc
.BindFlags
);
4002 ok_(__FILE__
, line
)(!texture_desc
.CPUAccessFlags
,
4003 "Got unexpected CPUAccessFlags %#x.\n", texture_desc
.CPUAccessFlags
);
4004 ok_(__FILE__
, line
)(!texture_desc
.MiscFlags
, "Got unexpected MiscFlags %#x.\n", texture_desc
.MiscFlags
);
4007 #define check_resource_desc(a, b) check_resource_desc_(__LINE__, a, b)
4008 static void check_resource_desc_(unsigned int line
, ID3D12Resource
*resource
,
4009 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
4011 D3D12_RESOURCE_DESC resource_desc
;
4013 resource_desc
= ID3D12Resource_GetDesc(resource
);
4014 ok_(__FILE__
, line
)(resource_desc
.Dimension
== D3D12_RESOURCE_DIMENSION_TEXTURE2D
,
4015 "Got unexpected Dimension %#x.\n", resource_desc
.Dimension
);
4016 ok_(__FILE__
, line
)(resource_desc
.Width
== swapchain_desc
->BufferDesc
.Width
, "Got Width %s, expected %u.\n",
4017 wine_dbgstr_longlong(resource_desc
.Width
), swapchain_desc
->BufferDesc
.Width
);
4018 ok_(__FILE__
, line
)(resource_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
4019 "Got Height %u, expected %u.\n", resource_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
4020 ok_(__FILE__
, line
)(resource_desc
.DepthOrArraySize
== 1,
4021 "Got unexpected DepthOrArraySize %u.\n", resource_desc
.DepthOrArraySize
);
4022 ok_(__FILE__
, line
)(resource_desc
.MipLevels
== 1,
4023 "Got unexpected MipLevels %u.\n", resource_desc
.MipLevels
);
4024 ok_(__FILE__
, line
)(resource_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
4025 "Got Format %#x, expected %#x.\n", resource_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
4026 ok_(__FILE__
, line
)(resource_desc
.SampleDesc
.Count
== 1,
4027 "Got unexpected SampleDesc.Count %u.\n", resource_desc
.SampleDesc
.Count
);
4028 ok_(__FILE__
, line
)(!resource_desc
.SampleDesc
.Quality
,
4029 "Got unexpected SampleDesc.Quality %u.\n", resource_desc
.SampleDesc
.Quality
);
4030 ok_(__FILE__
, line
)(resource_desc
.Layout
== D3D12_TEXTURE_LAYOUT_UNKNOWN
,
4031 "Got unexpected Layout %#x.\n", resource_desc
.Layout
);
4034 static void test_swapchain_resize(IUnknown
*device
, BOOL is_d3d12
)
4036 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4037 DXGI_SWAP_EFFECT swap_effect
;
4038 IDXGISwapChain3
*swapchain3
;
4039 IUnknown
*present_queue
[2];
4040 IDXGISwapChain
*swapchain
;
4041 ID3D12Resource
*resource
;
4042 ID3D10Texture2D
*texture
;
4043 HRESULT hr
, expected_hr
;
4044 IDXGISurface
*surface
;
4045 IDXGIFactory
*factory
;
4046 RECT client_rect
, r
;
4052 get_factory(device
, is_d3d12
, &factory
);
4054 window
= create_window();
4055 ret
= GetClientRect(window
, &client_rect
);
4056 ok(ret
, "Failed to get client rect.\n");
4058 swap_effect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4060 swapchain_desc
.BufferDesc
.Width
= 640;
4061 swapchain_desc
.BufferDesc
.Height
= 480;
4062 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4063 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
4064 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4065 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4066 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4067 swapchain_desc
.SampleDesc
.Count
= 1;
4068 swapchain_desc
.SampleDesc
.Quality
= 0;
4069 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4070 swapchain_desc
.BufferCount
= 2;
4071 swapchain_desc
.OutputWindow
= window
;
4072 swapchain_desc
.Windowed
= TRUE
;
4073 swapchain_desc
.SwapEffect
= swap_effect
;
4074 swapchain_desc
.Flags
= 0;
4076 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4077 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
4078 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4079 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4080 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4081 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4082 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4083 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4084 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4085 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4086 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4087 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4088 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4090 ret
= GetClientRect(window
, &r
);
4091 ok(ret
, "Failed to get client rect.\n");
4092 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4093 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4095 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4096 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4097 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4098 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4099 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4100 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4101 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4102 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4103 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4104 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4105 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4106 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4107 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4108 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4109 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4110 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4111 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4112 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4113 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4114 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4115 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4116 ok(!swapchain_desc
.SampleDesc
.Quality
,
4117 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4118 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4119 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4120 ok(swapchain_desc
.BufferCount
== 2,
4121 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4122 ok(swapchain_desc
.OutputWindow
== window
,
4123 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4124 ok(swapchain_desc
.Windowed
,
4125 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4126 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4127 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4128 ok(!swapchain_desc
.Flags
,
4129 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4132 check_surface_desc(surface
, &swapchain_desc
);
4134 check_texture_desc(texture
, &swapchain_desc
);
4136 check_resource_desc(resource
, &swapchain_desc
);
4138 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4139 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4141 ret
= GetClientRect(window
, &r
);
4142 ok(ret
, "Failed to get client rect.\n");
4143 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4144 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4146 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4147 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4148 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4149 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4150 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4151 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4152 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4153 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4154 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4155 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4156 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4157 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4158 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4159 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4160 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4161 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4162 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4163 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4164 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4165 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4166 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4167 ok(!swapchain_desc
.SampleDesc
.Quality
,
4168 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4169 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4170 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4171 ok(swapchain_desc
.BufferCount
== 2,
4172 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4173 ok(swapchain_desc
.OutputWindow
== window
,
4174 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4175 ok(swapchain_desc
.Windowed
,
4176 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4177 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4178 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4179 ok(!swapchain_desc
.Flags
,
4180 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4184 check_surface_desc(surface
, &swapchain_desc
);
4185 IDXGISurface_Release(surface
);
4189 check_texture_desc(texture
, &swapchain_desc
);
4190 ID3D10Texture2D_Release(texture
);
4194 check_resource_desc(resource
, &swapchain_desc
);
4195 ID3D12Resource_Release(resource
);
4198 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4199 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4200 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4201 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4202 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4203 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4204 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4205 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4206 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4207 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4208 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4209 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4210 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4212 ret
= GetClientRect(window
, &r
);
4213 ok(ret
, "Failed to get client rect.\n");
4214 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4215 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4217 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4218 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4219 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4220 ok(swapchain_desc
.BufferDesc
.Width
== 320,
4221 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4222 ok(swapchain_desc
.BufferDesc
.Height
== 240,
4223 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4224 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4225 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4226 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4227 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4228 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4229 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4230 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4231 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4232 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4233 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4234 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4235 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4236 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4237 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4238 ok(!swapchain_desc
.SampleDesc
.Quality
,
4239 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4240 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4241 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4242 ok(swapchain_desc
.BufferCount
== 2,
4243 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4244 ok(swapchain_desc
.OutputWindow
== window
,
4245 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4246 ok(swapchain_desc
.Windowed
,
4247 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4248 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4249 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4250 ok(!swapchain_desc
.Flags
,
4251 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4255 check_surface_desc(surface
, &swapchain_desc
);
4256 IDXGISurface_Release(surface
);
4260 check_texture_desc(texture
, &swapchain_desc
);
4261 ID3D10Texture2D_Release(texture
);
4265 check_resource_desc(resource
, &swapchain_desc
);
4266 ID3D12Resource_Release(resource
);
4269 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4270 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4272 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4273 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4274 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4275 ok(swapchain_desc
.BufferDesc
.Width
== client_rect
.right
- client_rect
.left
,
4276 "Got unexpected BufferDesc.Width %u, expected %u.\n",
4277 swapchain_desc
.BufferDesc
.Width
, client_rect
.right
- client_rect
.left
);
4278 ok(swapchain_desc
.BufferDesc
.Height
== client_rect
.bottom
- client_rect
.top
,
4279 "Got unexpected bufferDesc.Height %u, expected %u.\n",
4280 swapchain_desc
.BufferDesc
.Height
, client_rect
.bottom
- client_rect
.top
);
4281 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4282 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4283 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4284 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4285 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4286 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4287 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4288 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4289 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4290 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4291 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4292 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4293 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4294 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4295 ok(!swapchain_desc
.SampleDesc
.Quality
,
4296 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4297 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4298 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4299 ok(swapchain_desc
.BufferCount
== 2,
4300 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4301 ok(swapchain_desc
.OutputWindow
== window
,
4302 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4303 ok(swapchain_desc
.Windowed
,
4304 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4305 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4306 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4307 ok(!swapchain_desc
.Flags
,
4308 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4312 present_queue
[0] = device
;
4313 present_queue
[1] = device
;
4314 if (IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
) == E_NOINTERFACE
)
4316 skip("IDXGISwapChain3 is not supported.\n");
4320 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4321 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4322 IDXGISwapChain3_Release(swapchain3
);
4326 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4327 ok(hr
== S_OK
, "Failed to resize buffers, hr %#x.\n", hr
);
4328 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, present_queue
);
4329 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4330 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4331 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4332 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4333 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4336 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4337 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4338 /* Windows validates node masks even when the buffer count is zero. It defaults to the current buffer count.
4339 * NULL queues cause some Windows versions to crash. */
4340 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4341 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Expected DXGI_ERROR_INVALID_CALL, got hr %#x.\n", hr
);
4342 IDXGISwapChain3_Release(swapchain3
);
4345 IDXGISwapChain_Release(swapchain
);
4346 DestroyWindow(window
);
4347 refcount
= IDXGIFactory_Release(factory
);
4348 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
4351 static void test_swapchain_parameters(void)
4353 DXGI_USAGE usage
, expected_usage
, broken_usage
;
4354 D3D10_TEXTURE2D_DESC d3d10_texture_desc
;
4355 D3D11_TEXTURE2D_DESC d3d11_texture_desc
;
4356 unsigned int expected_bind_flags
;
4357 ID3D10Texture2D
*d3d10_texture
;
4358 ID3D11Texture2D
*d3d11_texture
;
4359 DXGI_SWAP_CHAIN_DESC desc
;
4360 IDXGISwapChain
*swapchain
;
4361 IDXGIResource
*resource
;
4362 IDXGIAdapter
*adapter
;
4363 IDXGIFactory
*factory
;
4364 IDXGIDevice
*device
;
4375 DXGI_SWAP_EFFECT swap_effect
;
4376 HRESULT hr
, vista_hr
;
4377 UINT highest_accessible_buffer
;
4382 {TRUE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4383 {TRUE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4384 {TRUE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4385 {TRUE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4386 {TRUE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4388 {TRUE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4389 {TRUE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4390 {TRUE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4391 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4392 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4394 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4395 {TRUE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4396 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4397 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4398 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4400 {TRUE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4401 {TRUE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4402 {TRUE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4403 {TRUE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4404 {TRUE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4406 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4407 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4408 {TRUE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4409 {FALSE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4410 {FALSE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4412 {FALSE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4413 {FALSE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4414 {FALSE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4415 {FALSE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4416 {FALSE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4418 {FALSE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4419 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4420 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4421 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4422 {FALSE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4424 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4425 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4426 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4427 {FALSE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4428 {FALSE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4430 {FALSE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4431 {FALSE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4432 {FALSE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4433 {FALSE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4434 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4436 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4438 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
4439 * process. Disable it for now.
4440 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
4443 /* The following tests crash on Win10 1909
4444 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4445 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4446 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4447 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4448 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4449 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4450 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4451 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4452 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4455 static const DXGI_USAGE usage_tests
[] =
4458 DXGI_USAGE_BACK_BUFFER
,
4459 DXGI_USAGE_SHADER_INPUT
,
4460 DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4461 DXGI_USAGE_DISCARD_ON_PRESENT
,
4462 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
,
4463 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4464 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4465 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4466 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4469 if (!(device
= create_device(0)))
4471 skip("Failed to create device.\n");
4474 window
= create_window();
4476 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
4477 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
4479 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
4480 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
4481 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
4482 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
4483 IDXGIAdapter_Release(adapter
);
4485 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
4487 memset(&desc
, 0, sizeof(desc
));
4488 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4489 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4490 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4491 desc
.SampleDesc
.Count
= 1;
4492 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4493 desc
.OutputWindow
= window
;
4495 desc
.Windowed
= tests
[i
].windowed
;
4496 desc
.BufferCount
= tests
[i
].buffer_count
;
4497 desc
.SwapEffect
= tests
[i
].swap_effect
;
4499 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4500 ok(hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].vista_hr
)
4501 || (SUCCEEDED(tests
[i
].hr
) && hr
== DXGI_STATUS_OCCLUDED
),
4502 "Got unexpected hr %#x, test %u.\n", hr
, i
);
4506 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4507 todo_wine
ok(SUCCEEDED(hr
), "GetBuffer(0) failed, hr %#x, test %u.\n", hr
, i
);
4510 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4511 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
4513 IDXGISwapChain_Release(swapchain
);
4517 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4518 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4519 ok(SUCCEEDED(hr
), "Failed to get resource usage, hr %#x, test %u.\n", hr
, i
);
4520 ok((usage
& expected_usage
) == expected_usage
, "Got usage %x, expected %x, test %u.\n",
4521 usage
, expected_usage
, i
);
4523 IDXGIResource_Release(resource
);
4525 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4526 ok(SUCCEEDED(hr
), "Failed to get swapchain desc, hr %#x.\n", hr
);
4528 for (j
= 1; j
<= tests
[i
].highest_accessible_buffer
; j
++)
4530 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4531 ok(SUCCEEDED(hr
), "GetBuffer(%u) failed, hr %#x, test %u.\n", hr
, i
, j
);
4533 /* Buffers > 0 are supposed to be read only. This is the case except that in
4534 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
4535 * writable. This is not the case if an unsupported refresh rate is passed
4536 * for some reason, probably because the invalid refresh rate triggers a
4537 * kinda-sorta windowed mode.
4539 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
4542 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
4543 * the draw on the screen right away (Aero on or off doesn't matter), but
4544 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
4546 * Note that if the application doesn't have focus creating a fullscreen
4547 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
4548 * so use the Windowed property of the swapchain that was actually created. */
4549 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_READ_ONLY
;
4550 broken_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4552 if (desc
.Windowed
|| j
< tests
[i
].highest_accessible_buffer
)
4553 broken_usage
|= DXGI_USAGE_READ_ONLY
;
4555 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4556 ok(SUCCEEDED(hr
), "Failed to get resource usage, hr %#x, test %u, buffer %u.\n", hr
, i
, j
);
4557 ok(usage
== expected_usage
|| broken(usage
== broken_usage
),
4558 "Got usage %x, expected %x, test %u, buffer %u.\n",
4559 usage
, expected_usage
, i
, j
);
4561 IDXGIResource_Release(resource
);
4563 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4564 ok(hr
== DXGI_ERROR_INVALID_CALL
, "GetBuffer(%u) returned unexpected hr %#x, test %u.\n", j
, hr
, i
);
4566 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4567 ok(SUCCEEDED(hr
), "SetFullscreenState failed, hr %#x.\n", hr
);
4569 IDXGISwapChain_Release(swapchain
);
4572 for (i
= 0; i
< ARRAY_SIZE(usage_tests
); ++i
)
4574 usage
= usage_tests
[i
];
4576 memset(&desc
, 0, sizeof(desc
));
4577 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4578 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4579 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4580 desc
.SampleDesc
.Count
= 1;
4581 desc
.BufferUsage
= usage
;
4582 desc
.BufferCount
= 1;
4583 desc
.OutputWindow
= window
;
4584 desc
.Windowed
= TRUE
;
4585 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4586 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4587 ok(hr
== S_OK
, "Got unexpected hr %#x, test %u.\n", hr
, i
);
4589 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4590 ok(hr
== S_OK
, "Failed to get swapchain desc, hr %#x, test %u.\n", hr
, i
);
4591 todo_wine_if(usage
& ~(DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_SHADER_INPUT
))
4592 ok(desc
.BufferUsage
== usage
, "Got usage %#x, expected %#x, test %u.\n", desc
.BufferUsage
, usage
, i
);
4594 expected_bind_flags
= 0;
4595 if (usage
& DXGI_USAGE_RENDER_TARGET_OUTPUT
)
4596 expected_bind_flags
|= D3D11_BIND_RENDER_TARGET
;
4597 if (usage
& DXGI_USAGE_SHADER_INPUT
)
4598 expected_bind_flags
|= D3D11_BIND_SHADER_RESOURCE
;
4600 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&d3d10_texture
);
4601 ok(hr
== S_OK
, "Failed to get d3d10 texture, hr %#x, test %u.\n", hr
, i
);
4602 ID3D10Texture2D_GetDesc(d3d10_texture
, &d3d10_texture_desc
);
4603 ok(d3d10_texture_desc
.BindFlags
== expected_bind_flags
,
4604 "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
4605 d3d10_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4606 ID3D10Texture2D_Release(d3d10_texture
);
4608 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D11Texture2D
, (void **)&d3d11_texture
);
4609 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Failed to get d3d11 texture, hr %#x, test %u.\n", hr
, i
);
4612 ID3D11Texture2D_GetDesc(d3d11_texture
, &d3d11_texture_desc
);
4613 ok(d3d11_texture_desc
.BindFlags
== expected_bind_flags
,
4614 "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
4615 d3d11_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4616 ID3D11Texture2D_Release(d3d11_texture
);
4619 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4620 todo_wine
ok(hr
== S_OK
, "Failed to get buffer, hr %#x, test %u.\n", hr
, i
);
4623 IDXGISwapChain_Release(swapchain
);
4626 expected_usage
= usage
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
;
4627 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4628 ok(hr
== S_OK
, "Failed to get resource usage, hr %#x, test %u.\n", hr
, i
);
4629 ok(usage
== expected_usage
, "Got usage %x, expected %x, test %u.\n", usage
, expected_usage
, i
);
4630 IDXGIResource_Release(resource
);
4632 IDXGISwapChain_Release(swapchain
);
4636 memset(&desc
, 0, sizeof(desc
));
4637 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4638 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4639 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4640 desc
.SampleDesc
.Count
= 4;
4641 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4642 desc
.BufferCount
= 4;
4643 desc
.OutputWindow
= window
;
4644 desc
.Windowed
= TRUE
;
4645 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
;
4646 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4647 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4648 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
4649 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4650 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
4651 if (check_multisample_quality_levels(device
, desc
.BufferDesc
.Format
, desc
.SampleDesc
.Count
))
4653 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4654 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4655 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4656 IDXGISwapChain_Release(swapchain
);
4657 desc
.SwapEffect
= DXGI_SWAP_EFFECT_SEQUENTIAL
;
4658 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4659 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4660 IDXGISwapChain_Release(swapchain
);
4664 skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM.\n");
4667 IDXGIFactory_Release(factory
);
4668 IUnknown_Release(obj
);
4669 refcount
= IDXGIDevice_Release(device
);
4670 ok(!refcount
, "Device has %u references left.\n", refcount
);
4671 DestroyWindow(window
);
4674 static void test_swapchain_present(IUnknown
*device
, BOOL is_d3d12
)
4676 static const DWORD flags
[] = {0, DXGI_PRESENT_TEST
};
4677 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4678 IDXGISwapChain
*swapchain
;
4679 IDXGIFactory
*factory
;
4680 IDXGIOutput
*output
;
4686 get_factory(device
, is_d3d12
, &factory
);
4688 swapchain_desc
.BufferDesc
.Width
= 800;
4689 swapchain_desc
.BufferDesc
.Height
= 600;
4690 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4691 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4692 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4693 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4694 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4695 swapchain_desc
.SampleDesc
.Count
= 1;
4696 swapchain_desc
.SampleDesc
.Quality
= 0;
4697 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4698 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
4699 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
4700 swapchain_desc
.Windowed
= TRUE
;
4701 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4702 swapchain_desc
.Flags
= 0;
4704 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4705 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
4707 for (i
= 0; i
< 10; ++i
)
4709 hr
= IDXGISwapChain_Present(swapchain
, i
, 0);
4710 ok(hr
== (i
<= 4 ? S_OK
: DXGI_ERROR_INVALID_CALL
),
4711 "Got unexpected hr %#x for sync interval %u.\n", hr
, i
);
4713 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4714 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4716 for (i
= 0; i
< ARRAY_SIZE(flags
); ++i
)
4718 HWND occluding_window
= CreateWindowA("static", "occluding_window",
4719 WS_POPUP
| WS_VISIBLE
, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
4721 /* Another window covers the swapchain window. Not reported as occluded. */
4722 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4723 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4725 /* Minimised window. */
4726 ShowWindow(swapchain_desc
.OutputWindow
, SW_MINIMIZE
);
4727 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4728 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4729 ShowWindow(swapchain_desc
.OutputWindow
, SW_NORMAL
);
4731 /* Hidden window. */
4732 ShowWindow(swapchain_desc
.OutputWindow
, SW_HIDE
);
4733 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4734 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4735 ShowWindow(swapchain_desc
.OutputWindow
, SW_SHOW
);
4736 DestroyWindow(occluding_window
);
4738 /* Test that IDXGIOutput_ReleaseOwnership() makes the swapchain exit
4740 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4741 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
4742 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
4743 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
4745 skip("Test %u: Could not change fullscreen state.\n", i
);
4749 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4750 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4751 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4752 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4753 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4756 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
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 ok(!!output
, "Test %u: Got unexpected output.\n", i
);
4762 IDXGIOutput_ReleaseOwnership(output
);
4763 /* Still fullscreen. */
4765 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4766 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4767 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4768 /* Calling IDXGISwapChain_Present() will exit fullscreen. */
4769 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4770 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4772 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4773 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4774 /* Now fullscreen mode is exited. */
4775 if (!flags
[i
] && !is_d3d12
)
4776 /* Still fullscreen on vista and 2008. */
4777 todo_wine
ok(!fullscreen
|| broken(fullscreen
), "Test %u: Got unexpected fullscreen status.\n", i
);
4779 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4781 IDXGIOutput_Release(output
);
4783 /* Test creating a window when swapchain is in fullscreen.
4785 * The window should break the swapchain out of fullscreen mode on
4786 * d3d10/11. D3d12 is different, a new occluding window doesn't break
4787 * the swapchain out of fullscreen because d3d12 fullscreen swapchains
4788 * don't take exclusive ownership over the output, nor do they disable
4789 * compositing. D3d12 fullscreen mode acts just like borderless
4790 * fullscreen window mode. */
4791 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4792 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4794 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4795 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4796 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4797 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4798 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4799 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4800 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4802 occluding_window
= CreateWindowA("static", "occluding_window", WS_POPUP
, 0, 0, 400, 200, 0, 0, 0, 0);
4803 /* An invisible window doesn't cause the swapchain to exit fullscreen
4805 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4806 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4807 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4808 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4810 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4811 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4812 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4813 /* A visible, but with bottom z-order window still causes the
4814 * swapchain to exit fullscreen mode. */
4815 SetWindowPos(occluding_window
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
4816 ShowWindow(occluding_window
, SW_SHOW
);
4817 /* Fullscreen mode takes a while to exit. */
4819 wait_fullscreen_state(swapchain
, FALSE
, TRUE
);
4821 /* No longer fullscreen before calling IDXGISwapChain_Present() except
4824 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4825 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4826 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4827 "Test %u: Got unexpected fullscreen status.\n", i
);
4829 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4830 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4831 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4832 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4833 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4836 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4837 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4838 if (flags
[i
] == DXGI_PRESENT_TEST
)
4839 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4840 "Test %u: Got unexpected fullscreen status.\n", i
);
4842 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4844 /* Even though d3d12 doesn't exit fullscreen, a
4845 * IDXGISwapChain_ResizeBuffers() is still needed for subsequent
4846 * IDXGISwapChain_Present() calls to work, otherwise they will return
4847 * DXGI_ERROR_INVALID_CALL */
4848 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4849 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4850 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4851 if (flags
[i
] == DXGI_PRESENT_TEST
)
4852 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4853 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4855 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4857 /* Trying to break out of fullscreen mode again. This time, don't call
4858 * IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */
4859 ShowWindow(occluding_window
, SW_HIDE
);
4860 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4861 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4862 ShowWindow(occluding_window
, SW_SHOW
);
4864 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4865 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4866 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4867 /* hr == S_OK on vista and 2008 */
4868 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4869 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4871 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4872 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4873 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4874 if (flags
[i
] == DXGI_PRESENT_TEST
)
4876 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4877 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4878 /* IDXGISwapChain_Present() without flags refreshes the occlusion
4880 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4881 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4882 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4883 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4884 "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4885 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4886 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4887 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
4888 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4892 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4895 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4896 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4897 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4899 DestroyWindow(occluding_window
);
4901 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4902 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4903 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4904 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4906 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4907 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4908 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4909 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
4912 wait_device_idle(device
);
4914 IDXGISwapChain_Release(swapchain
);
4915 DestroyWindow(swapchain_desc
.OutputWindow
);
4916 refcount
= IDXGIFactory_Release(factory
);
4917 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
4920 static void test_swapchain_backbuffer_index(IUnknown
*device
, BOOL is_d3d12
)
4922 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4923 unsigned int index
, expected_index
;
4924 IDXGISwapChain3
*swapchain3
;
4925 IDXGISwapChain
*swapchain
;
4926 HRESULT hr
, expected_hr
;
4927 IDXGIFactory
*factory
;
4933 static const DXGI_SWAP_EFFECT swap_effects
[] =
4935 DXGI_SWAP_EFFECT_DISCARD
,
4936 DXGI_SWAP_EFFECT_SEQUENTIAL
,
4937 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
,
4938 DXGI_SWAP_EFFECT_FLIP_DISCARD
,
4941 get_factory(device
, is_d3d12
, &factory
);
4943 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4944 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4945 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4946 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4947 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4948 swapchain_desc
.SampleDesc
.Count
= 1;
4949 swapchain_desc
.SampleDesc
.Quality
= 0;
4950 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4951 swapchain_desc
.BufferCount
= 4;
4952 swapchain_desc
.OutputWindow
= create_window();
4953 swapchain_desc
.Windowed
= TRUE
;
4954 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4955 swapchain_desc
.Flags
= 0;
4957 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
4958 ok(ret
, "Failed to get client rect.\n");
4959 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
4960 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
4962 for (i
= 0; i
< ARRAY_SIZE(swap_effects
); ++i
)
4964 swapchain_desc
.SwapEffect
= swap_effects
[i
];
4965 expected_hr
= is_d3d12
&& !is_flip_model(swap_effects
[i
]) ? DXGI_ERROR_INVALID_CALL
: S_OK
;
4966 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4967 ok(hr
== expected_hr
, "Got hr %#x, expected %#x.\n", hr
, expected_hr
);
4971 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
);
4972 if (hr
== E_NOINTERFACE
)
4974 skip("IDXGISwapChain3 is not supported.\n");
4975 IDXGISwapChain_Release(swapchain
);
4979 for (j
= 0; j
< 2 * swapchain_desc
.BufferCount
; ++j
)
4981 index
= IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3
);
4982 expected_index
= is_d3d12
? j
% swapchain_desc
.BufferCount
: 0;
4983 ok(index
== expected_index
, "Got back buffer index %u, expected %u.\n", index
, expected_index
);
4984 hr
= IDXGISwapChain3_Present(swapchain3
, 0, 0);
4985 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
4988 wait_device_idle(device
);
4990 IDXGISwapChain3_Release(swapchain3
);
4991 refcount
= IDXGISwapChain_Release(swapchain
);
4992 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
4996 DestroyWindow(swapchain_desc
.OutputWindow
);
4997 refcount
= IDXGIFactory_Release(factory
);
4998 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
5001 static void test_swapchain_formats(IUnknown
*device
, BOOL is_d3d12
)
5003 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5004 IDXGISwapChain
*swapchain
;
5005 HRESULT hr
, expected_hr
;
5006 IDXGIFactory
*factory
;
5015 DXGI_SWAP_EFFECT swap_effect
;
5020 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_DISCARD
, FALSE
},
5021 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_SEQUENTIAL
, FALSE
},
5022 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5023 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5024 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5025 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5026 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5027 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5028 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5029 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5030 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5031 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5032 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5033 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5034 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5035 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5036 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5037 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5038 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5039 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5040 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5041 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5042 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5043 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5044 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5045 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5046 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5047 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5048 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5049 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5052 get_factory(device
, is_d3d12
, &factory
);
5054 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5055 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5056 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5057 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5058 swapchain_desc
.SampleDesc
.Count
= 1;
5059 swapchain_desc
.SampleDesc
.Quality
= 0;
5060 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5061 swapchain_desc
.BufferCount
= 4;
5062 swapchain_desc
.OutputWindow
= create_window();
5063 swapchain_desc
.Windowed
= TRUE
;
5064 swapchain_desc
.Flags
= 0;
5066 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
5067 ok(ret
, "Failed to get client rect.\n");
5068 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
5069 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
5071 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
5073 if (is_d3d12
&& !is_flip_model(tests
[i
].swap_effect
))
5076 swapchain_desc
.BufferDesc
.Format
= tests
[i
].format
;
5077 swapchain_desc
.SwapEffect
= tests
[i
].swap_effect
;
5078 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
5079 expected_hr
= tests
[i
].supported
? S_OK
: DXGI_ERROR_INVALID_CALL
;
5080 if (tests
[i
].format
== DXGI_FORMAT_UNKNOWN
&& !is_d3d12
)
5081 expected_hr
= E_INVALIDARG
;
5082 ok(hr
== expected_hr
5083 /* Flip presentation model not supported. */
5084 || broken(hr
== DXGI_ERROR_INVALID_CALL
&& is_flip_model(tests
[i
].swap_effect
) && !is_d3d12
),
5085 "Test %u, d3d12 %#x: Got hr %#x, expected %#x.\n", i
, is_d3d12
, hr
, expected_hr
);
5089 refcount
= IDXGISwapChain_Release(swapchain
);
5090 ok(!refcount
, "Swapchain has %u references left.\n", refcount
);
5094 DestroyWindow(swapchain_desc
.OutputWindow
);
5095 refcount
= IDXGIFactory_Release(factory
);
5096 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
5099 static void test_maximum_frame_latency(void)
5101 IDXGIDevice1
*device1
;
5102 IDXGIDevice
*device
;
5107 if (!(device
= create_device(0)))
5109 skip("Failed to create device.\n");
5113 if (SUCCEEDED(IDXGIDevice_QueryInterface(device
, &IID_IDXGIDevice1
, (void **)&device1
)))
5115 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, NULL
);
5116 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5118 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5119 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5120 ok(max_latency
== DEFAULT_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5122 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
);
5123 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5124 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5125 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5126 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5128 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
+ 1);
5129 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5130 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5131 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5132 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5134 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, 0);
5135 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5136 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5137 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5138 /* 0 does not reset to the default frame latency on all Windows versions. */
5139 ok(max_latency
== DEFAULT_FRAME_LATENCY
|| broken(!max_latency
),
5140 "Got unexpected maximum frame latency %u.\n", max_latency
);
5142 IDXGIDevice1_Release(device1
);
5146 win_skip("IDXGIDevice1 is not implemented.\n");
5149 refcount
= IDXGIDevice_Release(device
);
5150 ok(!refcount
, "Device has %u references left.\n", refcount
);
5153 static void test_output_desc(void)
5155 IDXGIAdapter
*adapter
, *adapter2
;
5156 IDXGIOutput
*output
, *output2
;
5157 DXGI_OUTPUT_DESC desc
;
5158 IDXGIFactory
*factory
;
5163 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5164 ok(SUCCEEDED(hr
), "Failed to create DXGI factory, hr %#x.\n", hr
);
5168 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter
);
5169 if (hr
== DXGI_ERROR_NOT_FOUND
)
5171 ok(SUCCEEDED(hr
), "Failed to enumerate adapter %u, hr %#x.\n", i
, hr
);
5173 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter2
);
5174 ok(SUCCEEDED(hr
), "Failed to enumerate adapter %u, hr %#x.\n", i
, hr
);
5175 ok(adapter
!= adapter2
, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter
, adapter2
);
5176 refcount
= get_refcount(adapter
);
5177 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5178 IDXGIAdapter_Release(adapter2
);
5180 refcount
= get_refcount(factory
);
5181 ok(refcount
== 2, "Get unexpected refcount %u.\n", refcount
);
5182 refcount
= get_refcount(adapter
);
5183 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5187 MONITORINFOEXW monitor_info
;
5190 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output
);
5191 if (hr
== DXGI_ERROR_NOT_FOUND
)
5193 ok(SUCCEEDED(hr
), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5195 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output2
);
5196 ok(SUCCEEDED(hr
), "Failed to enumerate output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5197 ok(output
!= output2
, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output
, output2
);
5198 refcount
= get_refcount(output
);
5199 ok(refcount
== 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount
, j
, i
);
5200 IDXGIOutput_Release(output2
);
5202 refcount
= get_refcount(factory
);
5203 ok(refcount
== 2, "Get unexpected refcount %u.\n", refcount
);
5204 refcount
= get_refcount(adapter
);
5205 ok(refcount
== 2, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5206 refcount
= get_refcount(output
);
5207 ok(refcount
== 1, "Get unexpected refcount %u for output %u, adapter %u.\n", refcount
, j
, i
);
5209 hr
= IDXGIOutput_GetDesc(output
, &desc
);
5210 ok(SUCCEEDED(hr
), "Failed to get desc for output %u on adapter %u, hr %#x.\n", j
, i
, hr
);
5212 monitor_info
.cbSize
= sizeof(monitor_info
);
5213 ret
= GetMonitorInfoW(desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
5214 ok(ret
, "Failed to get monitor info.\n");
5215 ok(!lstrcmpW(desc
.DeviceName
, monitor_info
.szDevice
), "Got unexpected device name %s, expected %s.\n",
5216 wine_dbgstr_w(desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
5217 ok(EqualRect(&desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
5218 "Got unexpected desktop coordinates %s, expected %s.\n",
5219 wine_dbgstr_rect(&desc
.DesktopCoordinates
),
5220 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
5222 IDXGIOutput_Release(output
);
5223 refcount
= get_refcount(adapter
);
5224 ok(refcount
== 1, "Get unexpected refcount %u for adapter %u.\n", refcount
, i
);
5227 IDXGIAdapter_Release(adapter
);
5228 refcount
= get_refcount(factory
);
5229 ok(refcount
== 1, "Get unexpected refcount %u.\n", refcount
);
5232 refcount
= IDXGIFactory_Release(factory
);
5233 ok(!refcount
, "IDXGIFactory has %u references left.\n", refcount
);
5238 IDXGIFactory IDXGIFactory_iface
;
5239 IDXGIFactory
*wrapped_iface
;
5240 unsigned int wrapped_adapter_count
;
5243 static inline struct dxgi_factory
*impl_from_IDXGIFactory(IDXGIFactory
*iface
)
5245 return CONTAINING_RECORD(iface
, struct dxgi_factory
, IDXGIFactory_iface
);
5248 static HRESULT STDMETHODCALLTYPE
dxgi_factory_QueryInterface(IDXGIFactory
*iface
, REFIID iid
, void **out
)
5250 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5252 if (IsEqualGUID(iid
, &IID_IDXGIFactory
)
5253 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5254 || IsEqualGUID(iid
, &IID_IUnknown
))
5256 IDXGIFactory_AddRef(iface
);
5260 return IDXGIFactory_QueryInterface(factory
->wrapped_iface
, iid
, out
);
5263 static ULONG STDMETHODCALLTYPE
dxgi_factory_AddRef(IDXGIFactory
*iface
)
5265 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5266 return IDXGIFactory_AddRef(factory
->wrapped_iface
);
5269 static ULONG STDMETHODCALLTYPE
dxgi_factory_Release(IDXGIFactory
*iface
)
5271 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5272 return IDXGIFactory_Release(factory
->wrapped_iface
);
5275 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateData(IDXGIFactory
*iface
,
5276 REFGUID guid
, UINT data_size
, const void *data
)
5278 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5279 return IDXGIFactory_SetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5282 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateDataInterface(IDXGIFactory
*iface
,
5283 REFGUID guid
, const IUnknown
*object
)
5285 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5286 return IDXGIFactory_SetPrivateDataInterface(factory
->wrapped_iface
, guid
, object
);
5289 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetPrivateData(IDXGIFactory
*iface
,
5290 REFGUID guid
, UINT
*data_size
, void *data
)
5292 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5293 return IDXGIFactory_GetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5296 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetParent(IDXGIFactory
*iface
, REFIID iid
, void **parent
)
5298 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5299 return IDXGIFactory_GetParent(factory
->wrapped_iface
, iid
, parent
);
5302 static HRESULT STDMETHODCALLTYPE
dxgi_factory_EnumAdapters(IDXGIFactory
*iface
,
5303 UINT adapter_idx
, IDXGIAdapter
**adapter
)
5305 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5308 if (SUCCEEDED(hr
= IDXGIFactory_EnumAdapters(factory
->wrapped_iface
, adapter_idx
, adapter
)))
5309 ++factory
->wrapped_adapter_count
;
5313 static HRESULT STDMETHODCALLTYPE
dxgi_factory_MakeWindowAssociation(IDXGIFactory
*iface
,
5314 HWND window
, UINT flags
)
5316 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5317 return IDXGIFactory_MakeWindowAssociation(factory
->wrapped_iface
, window
, flags
);
5320 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetWindowAssociation(IDXGIFactory
*iface
, HWND
*window
)
5322 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5323 return IDXGIFactory_GetWindowAssociation(factory
->wrapped_iface
, window
);
5326 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSwapChain(IDXGIFactory
*iface
,
5327 IUnknown
*device
, DXGI_SWAP_CHAIN_DESC
*desc
, IDXGISwapChain
**swapchain
)
5329 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5330 return IDXGIFactory_CreateSwapChain(factory
->wrapped_iface
, device
, desc
, swapchain
);
5333 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSoftwareAdapter(IDXGIFactory
*iface
,
5334 HMODULE swrast
, IDXGIAdapter
**adapter
)
5336 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5337 return IDXGIFactory_CreateSoftwareAdapter(factory
->wrapped_iface
, swrast
, adapter
);
5340 static const struct IDXGIFactoryVtbl dxgi_factory_vtbl
=
5342 dxgi_factory_QueryInterface
,
5343 dxgi_factory_AddRef
,
5344 dxgi_factory_Release
,
5345 dxgi_factory_SetPrivateData
,
5346 dxgi_factory_SetPrivateDataInterface
,
5347 dxgi_factory_GetPrivateData
,
5348 dxgi_factory_GetParent
,
5349 dxgi_factory_EnumAdapters
,
5350 dxgi_factory_MakeWindowAssociation
,
5351 dxgi_factory_GetWindowAssociation
,
5352 dxgi_factory_CreateSwapChain
,
5353 dxgi_factory_CreateSoftwareAdapter
,
5358 IDXGIAdapter IDXGIAdapter_iface
;
5359 IDXGIAdapter
*wrapped_iface
;
5360 struct dxgi_factory factory
;
5361 unsigned int wrapped_output_count
;
5364 static inline struct dxgi_adapter
*impl_from_IDXGIAdapter(IDXGIAdapter
*iface
)
5366 return CONTAINING_RECORD(iface
, struct dxgi_adapter
, IDXGIAdapter_iface
);
5369 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryInterface(IDXGIAdapter
*iface
, REFIID iid
, void **out
)
5371 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5373 if (IsEqualGUID(iid
, &IID_IDXGIAdapter
)
5374 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5375 || IsEqualGUID(iid
, &IID_IUnknown
))
5377 IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5381 return IDXGIAdapter_QueryInterface(adapter
->wrapped_iface
, iid
, out
);
5384 static ULONG STDMETHODCALLTYPE
dxgi_adapter_AddRef(IDXGIAdapter
*iface
)
5386 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5387 return IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5390 static ULONG STDMETHODCALLTYPE
dxgi_adapter_Release(IDXGIAdapter
*iface
)
5392 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5393 return IDXGIAdapter_Release(adapter
->wrapped_iface
);
5396 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateData(IDXGIAdapter
*iface
,
5397 REFGUID guid
, UINT data_size
, const void *data
)
5399 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5400 return IDXGIAdapter_SetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5403 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateDataInterface(IDXGIAdapter
*iface
,
5404 REFGUID guid
, const IUnknown
*object
)
5406 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5407 return IDXGIAdapter_SetPrivateDataInterface(adapter
->wrapped_iface
, guid
, object
);
5410 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetPrivateData(IDXGIAdapter
*iface
,
5411 REFGUID guid
, UINT
*data_size
, void *data
)
5413 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5414 return IDXGIAdapter_GetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5417 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetParent(IDXGIAdapter
*iface
, REFIID iid
, void **parent
)
5419 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5420 return IDXGIFactory_QueryInterface(&adapter
->factory
.IDXGIFactory_iface
, iid
, parent
);
5423 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_EnumOutputs(IDXGIAdapter
*iface
,
5424 UINT output_idx
, IDXGIOutput
**output
)
5426 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5429 if (SUCCEEDED(hr
= IDXGIAdapter_EnumOutputs(adapter
->wrapped_iface
, output_idx
, output
)))
5430 ++adapter
->wrapped_output_count
;
5434 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc(IDXGIAdapter
*iface
, DXGI_ADAPTER_DESC
*desc
)
5436 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5437 return IDXGIAdapter_GetDesc(adapter
->wrapped_iface
, desc
);
5440 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter
*iface
,
5441 REFGUID guid
, LARGE_INTEGER
*umd_version
)
5443 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5444 return IDXGIAdapter_CheckInterfaceSupport(adapter
->wrapped_iface
, guid
, umd_version
);
5447 static const struct IDXGIAdapterVtbl dxgi_adapter_vtbl
=
5449 dxgi_adapter_QueryInterface
,
5450 dxgi_adapter_AddRef
,
5451 dxgi_adapter_Release
,
5452 dxgi_adapter_SetPrivateData
,
5453 dxgi_adapter_SetPrivateDataInterface
,
5454 dxgi_adapter_GetPrivateData
,
5455 dxgi_adapter_GetParent
,
5456 dxgi_adapter_EnumOutputs
,
5457 dxgi_adapter_GetDesc
,
5458 dxgi_adapter_CheckInterfaceSupport
,
5461 static void test_object_wrapping(void)
5463 struct dxgi_adapter wrapper
;
5464 DXGI_ADAPTER_DESC desc
;
5465 IDXGIAdapter
*adapter
;
5466 IDXGIFactory
*factory
;
5467 ID3D10Device1
*device
;
5471 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5472 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
5474 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5475 if (hr
== DXGI_ERROR_NOT_FOUND
)
5477 skip("Could not enumerate adapters.\n");
5478 IDXGIFactory_Release(factory
);
5481 ok(hr
== S_OK
, "Failed to enumerate adapter, hr %#x.\n", hr
);
5483 wrapper
.IDXGIAdapter_iface
.lpVtbl
= &dxgi_adapter_vtbl
;
5484 wrapper
.wrapped_iface
= adapter
;
5485 wrapper
.factory
.IDXGIFactory_iface
.lpVtbl
= &dxgi_factory_vtbl
;
5486 wrapper
.factory
.wrapped_iface
= factory
;
5487 wrapper
.factory
.wrapped_adapter_count
= 0;
5488 wrapper
.wrapped_output_count
= 0;
5490 hr
= D3D10CreateDevice1(&wrapper
.IDXGIAdapter_iface
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
5491 0, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
);
5494 refcount
= ID3D10Device1_Release(device
);
5495 ok(!refcount
, "Device has %u references left.\n", refcount
);
5498 hr
= IDXGIAdapter_GetDesc(&wrapper
.IDXGIAdapter_iface
, &desc
);
5499 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#x.\n", hr
);
5500 ok(!wrapper
.factory
.wrapped_adapter_count
, "Got unexpected wrapped adapter count %u.\n",
5501 wrapper
.factory
.wrapped_adapter_count
);
5502 ok(!wrapper
.wrapped_output_count
, "Got unexpected wrapped output count %u.\n", wrapper
.wrapped_output_count
);
5504 refcount
= IDXGIAdapter_Release(&wrapper
.IDXGIAdapter_iface
);
5505 ok(!refcount
, "Adapter has %u references left.\n", refcount
);
5506 refcount
= IDXGIFactory_Release(factory
);
5507 ok(!refcount
, "Factory has %u references left.\n", refcount
);
5516 static BOOL CALLBACK
enum_monitor_proc(HMONITOR monitor
, HDC dc
, RECT
*rect
, LPARAM lparam
)
5518 struct adapter_info
*adapter_info
= (struct adapter_info
*)lparam
;
5519 MONITORINFOEXW monitor_info
;
5521 monitor_info
.cbSize
= sizeof(monitor_info
);
5522 if (GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
)
5523 && !lstrcmpiW(adapter_info
->name
, monitor_info
.szDevice
))
5525 adapter_info
->monitor
= monitor
;
5532 static HMONITOR
get_monitor(const WCHAR
*adapter_name
)
5534 struct adapter_info info
= {adapter_name
, NULL
};
5536 EnumDisplayMonitors(NULL
, NULL
, enum_monitor_proc
, (LPARAM
)&info
);
5537 return info
.monitor
;
5540 static void test_multi_adapter(void)
5542 unsigned int output_count
= 0, expected_output_count
= 0;
5543 unsigned int adapter_index
, output_index
, device_index
;
5544 DXGI_OUTPUT_DESC old_output_desc
, output_desc
;
5545 DXGI_ADAPTER_DESC1 adapter_desc1
;
5546 DXGI_ADAPTER_DESC adapter_desc
;
5547 DISPLAY_DEVICEW display_device
;
5548 MONITORINFO monitor_info
;
5549 DEVMODEW old_mode
, mode
;
5550 IDXGIAdapter1
*adapter1
;
5551 IDXGIFactory
*factory
;
5552 IDXGIAdapter
*adapter
;
5553 IDXGIOutput
*output
;
5559 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
)))
5561 skip("Failed to create IDXGIFactory, hr %#x.\n", hr
);
5565 hr
= IDXGIFactory_EnumAdapters(factory
, 0, NULL
);
5566 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
5568 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5569 if (hr
== DXGI_ERROR_NOT_FOUND
)
5571 skip("Could not enumerate adapters.\n");
5572 IDXGIFactory_Release(factory
);
5575 ok(hr
== S_OK
, "Failed to enumerate adapter, hr %#x.\n", hr
);
5577 for (adapter_index
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)); ++adapter_index
)
5579 for (output_index
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
)); ++output_index
)
5581 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5582 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5586 display_device
.cb
= sizeof(display_device
);
5587 for (device_index
= 0; EnumDisplayDevicesW(NULL
, device_index
, &display_device
, 0); ++device_index
)
5589 if (!lstrcmpiW(display_device
.DeviceName
, output_desc
.DeviceName
))
5595 ok(found
, "Adapter %u output %u: Failed to find device %s.\n",
5596 adapter_index
, output_index
, wine_dbgstr_w(output_desc
.DeviceName
));
5598 ok(display_device
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
5599 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5600 output_index
, display_device
.StateFlags
);
5601 if (!adapter_index
&& !output_index
)
5602 ok(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
,
5603 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5604 output_index
, display_device
.StateFlags
);
5606 ok(!(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
),
5607 "Adapter %u output %u: Got unexpected state flags %#x.\n", adapter_index
,
5608 output_index
, display_device
.StateFlags
);
5610 /* Should have the same monitor handle. */
5611 monitor
= get_monitor(display_device
.DeviceName
);
5612 ok(!!monitor
, "Adapter %u output %u: Failed to find monitor %s.\n", adapter_index
,
5613 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5614 ok(monitor
== output_desc
.Monitor
,
5615 "Adapter %u output %u: Got unexpected monitor %p, expected %p.\n",
5616 adapter_index
, output_index
, monitor
, output_desc
.Monitor
);
5618 /* Should have the same monitor rectangle. */
5619 monitor_info
.cbSize
= sizeof(monitor_info
);
5620 ret
= GetMonitorInfoA(monitor
, &monitor_info
);
5621 ok(ret
, "Adapter %u output %u: Failed to get monitor info, error %#x.\n", adapter_index
,
5622 output_index
, GetLastError());
5623 ok(EqualRect(&monitor_info
.rcMonitor
, &output_desc
.DesktopCoordinates
),
5624 "Adapter %u output %u: Got unexpected output rect %s, expected %s.\n",
5625 adapter_index
, output_index
, wine_dbgstr_rect(&monitor_info
.rcMonitor
),
5626 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5630 /* Test output description after it got detached */
5631 if (display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
)
5633 IDXGIOutput_Release(output
);
5637 old_output_desc
= output_desc
;
5639 /* Save current display settings */
5640 memset(&old_mode
, 0, sizeof(old_mode
));
5641 old_mode
.dmSize
= sizeof(old_mode
);
5642 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &old_mode
);
5643 /* Win10 TestBots may return FALSE but it's actually successful */
5644 ok(ret
|| broken(!ret
),
5645 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n",
5646 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5650 memset(&mode
, 0, sizeof(mode
));
5651 mode
.dmSize
= sizeof(mode
);
5652 mode
.dmFields
= DM_POSITION
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
5653 mode
.dmPosition
= old_mode
.dmPosition
;
5654 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &mode
, NULL
,
5655 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5656 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5657 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5658 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5659 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5660 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5661 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5662 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5664 /* Check if it is really detached */
5665 memset(&mode
, 0, sizeof(mode
));
5666 mode
.dmSize
= sizeof(mode
);
5667 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &mode
);
5668 /* Win10 TestBots may return FALSE but it's actually successful */
5669 ok(ret
|| broken(!ret
) ,
5670 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#x.\n",
5671 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5673 if (mode
.dmPelsWidth
&& mode
.dmPelsHeight
)
5675 skip("Adapter %u output %u: Failed to detach device %s.\n", adapter_index
,
5676 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5677 IDXGIOutput_Release(output
);
5681 /* Only the AttachedToDesktop field is updated after an output is detached.
5682 * IDXGIAdapter_EnumOutputs() has to be called again to get other fields updated.
5683 * But resolution changes are reflected right away. This weird behaviour is currently
5684 * unimplemented in Wine */
5685 memset(&output_desc
, 0, sizeof(output_desc
));
5686 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5687 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5689 ok(!lstrcmpiW(output_desc
.DeviceName
, old_output_desc
.DeviceName
),
5690 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5691 output_index
, wine_dbgstr_w(old_output_desc
.DeviceName
),
5692 wine_dbgstr_w(output_desc
.DeviceName
));
5694 ok(EqualRect(&output_desc
.DesktopCoordinates
, &old_output_desc
.DesktopCoordinates
),
5695 "Adapter %u output %u: Expect desktop coordinates %s, got %s.\n",
5696 adapter_index
, output_index
,
5697 wine_dbgstr_rect(&old_output_desc
.DesktopCoordinates
),
5698 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5699 ok(!output_desc
.AttachedToDesktop
,
5700 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5702 ok(output_desc
.Rotation
== old_output_desc
.Rotation
,
5703 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5704 output_index
, old_output_desc
.Rotation
, output_desc
.Rotation
);
5706 ok(output_desc
.Monitor
== old_output_desc
.Monitor
,
5707 "Adapter %u output %u: Expect monitor %p, got %p.\n", adapter_index
,
5708 output_index
, old_output_desc
.Monitor
, output_desc
.Monitor
);
5709 IDXGIOutput_Release(output
);
5711 /* Call IDXGIAdapter_EnumOutputs() again to get up-to-date output description */
5712 hr
= IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
);
5713 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5715 memset(&output_desc
, 0, sizeof(output_desc
));
5716 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5717 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_index
,
5719 ok(!lstrcmpiW(output_desc
.DeviceName
, display_device
.DeviceName
),
5720 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5721 output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5722 wine_dbgstr_w(output_desc
.DeviceName
));
5723 ok(IsRectEmpty(&output_desc
.DesktopCoordinates
),
5724 "Adapter %u output %u: Expect desktop rect empty, got %s.\n", adapter_index
,
5725 output_index
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5726 ok(!output_desc
.AttachedToDesktop
,
5727 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5729 ok(output_desc
.Rotation
== DXGI_MODE_ROTATION_IDENTITY
,
5730 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5731 output_index
, DXGI_MODE_ROTATION_IDENTITY
, output_desc
.Rotation
);
5732 ok(!output_desc
.Monitor
, "Adapter %u output %u: Expect monitor NULL.\n", adapter_index
,
5735 /* Restore settings */
5736 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &old_mode
, NULL
,
5737 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5738 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5739 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5740 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5741 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5742 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5743 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %d.\n",
5744 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5746 IDXGIOutput_Release(output
);
5749 IDXGIAdapter_Release(adapter
);
5752 /* Windows 8+ always have a WARP adapter present at the end. */
5753 todo_wine
ok(adapter_index
>= 2 || broken(adapter_index
< 2) /* Windows 7 and before */,
5754 "Got unexpected adapter count %u.\n", adapter_index
);
5755 if (adapter_index
< 2)
5757 todo_wine
win_skip("WARP adapter missing, skipping tests.\n");
5761 hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
- 1, &adapter
);
5762 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5763 hr
= IDXGIAdapter_GetDesc(adapter
, &adapter_desc
);
5764 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5765 todo_wine
ok(!lstrcmpW(adapter_desc
.Description
, L
"Microsoft Basic Render Driver"),
5766 "Got unexpected description %s.\n", wine_dbgstr_w(adapter_desc
.Description
));
5767 todo_wine
ok(adapter_desc
.VendorId
== 0x1414,
5768 "Got unexpected vendor ID %#x.\n", adapter_desc
.VendorId
);
5769 todo_wine
ok(adapter_desc
.DeviceId
== 0x008c,
5770 "Got unexpected device ID %#x.\n", adapter_desc
.DeviceId
);
5771 ok(adapter_desc
.SubSysId
== 0x0000,
5772 "Got unexpected sub-system ID %#x.\n", adapter_desc
.SubSysId
);
5773 ok(adapter_desc
.Revision
== 0x0000,
5774 "Got unexpected revision %#x.\n", adapter_desc
.Revision
);
5775 todo_wine
ok(!adapter_desc
.DedicatedVideoMemory
,
5776 "Got unexpected DedicatedVideoMemory %#lx.\n", adapter_desc
.DedicatedVideoMemory
);
5777 ok(!adapter_desc
.DedicatedSystemMemory
,
5778 "Got unexpected DedicatedSystemMemory %#lx.\n", adapter_desc
.DedicatedSystemMemory
);
5780 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
5781 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#x.\n", hr
);
5784 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &adapter_desc1
);
5785 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
5786 todo_wine
ok(adapter_desc1
.Flags
== DXGI_ADAPTER_FLAG_SOFTWARE
,
5787 "Got unexpected flags %#x.\n", adapter_desc1
.Flags
);
5788 IDXGIAdapter1_Release(adapter1
);
5791 IDXGIAdapter_Release(adapter
);
5794 IDXGIFactory_Release(factory
);
5796 expected_output_count
= GetSystemMetrics(SM_CMONITORS
);
5797 ok(output_count
== expected_output_count
, "Expect output count %d, got %d\n",
5798 expected_output_count
, output_count
);
5803 unsigned int message
;
5805 WPARAM expect_wparam
;
5808 static BOOL expect_no_messages
;
5809 static const struct message
*expect_messages
;
5810 static const struct message
*expect_messages_broken
;
5812 static BOOL
check_message(const struct message
*expected
,
5813 HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5815 if (expected
->message
!= message
)
5818 if (expected
->check_wparam
)
5820 ok(wparam
== expected
->expect_wparam
,
5821 "Got unexpected wparam %lx for message %x, expected %lx.\n",
5822 wparam
, message
, expected
->expect_wparam
);
5828 static LRESULT CALLBACK
test_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5830 ok(!expect_no_messages
, "Got unexpected message %#x, hwnd %p, wparam %#lx, lparam %#lx.\n",
5831 message
, hwnd
, wparam
, lparam
);
5833 if (expect_messages
)
5835 if (check_message(expect_messages
, hwnd
, message
, wparam
, lparam
))
5839 if (expect_messages_broken
)
5841 if (check_message(expect_messages_broken
, hwnd
, message
, wparam
, lparam
))
5842 ++expect_messages_broken
;
5845 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
5848 static void test_swapchain_window_messages(void)
5850 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5851 IDXGISwapChain
*swapchain
;
5852 DXGI_MODE_DESC mode_desc
;
5853 IDXGIFactory
*factory
;
5854 IDXGIAdapter
*adapter
;
5855 IDXGIDevice
*device
;
5861 static const struct message enter_fullscreen_messages
[] =
5863 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5864 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5865 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5866 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5867 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5868 {WM_GETMINMAXINFO
, FALSE
, 0},
5869 {WM_NCCALCSIZE
, FALSE
, 0},
5870 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5871 {WM_MOVE
, FALSE
, 0},
5872 {WM_SIZE
, FALSE
, 0},
5875 static const struct message enter_fullscreen_messages_vista
[] =
5877 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5878 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5879 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5880 {WM_NCCALCSIZE
, FALSE
, 0},
5881 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5882 {WM_MOVE
, FALSE
, 0},
5883 {WM_SIZE
, FALSE
, 0},
5884 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5885 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5886 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5887 {WM_GETMINMAXINFO
, FALSE
, 0},
5888 {WM_NCCALCSIZE
, FALSE
, 0},
5889 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5890 {WM_SIZE
, FALSE
, 0},
5893 static const struct message leave_fullscreen_messages
[] =
5895 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5896 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5897 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5898 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5899 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5900 {WM_GETMINMAXINFO
, FALSE
, 0},
5901 {WM_NCCALCSIZE
, FALSE
, 0},
5902 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5903 {WM_MOVE
, FALSE
, 0},
5904 {WM_SIZE
, FALSE
, 0},
5907 static const struct message resize_target_messages
[] =
5909 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5910 {WM_GETMINMAXINFO
, FALSE
, 0},
5911 {WM_NCCALCSIZE
, FALSE
, 0},
5912 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5913 {WM_SIZE
, FALSE
, 0},
5917 if (!(device
= create_device(0)))
5919 skip("Failed to create device.\n");
5923 memset(&wc
, 0, sizeof(wc
));
5924 wc
.lpfnWndProc
= test_wndproc
;
5925 wc
.lpszClassName
= "dxgi_test_wndproc_wc";
5926 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
5927 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
5928 ok(!!window
, "Failed to create window.\n");
5930 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
5931 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
5932 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
5933 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
5934 IDXGIAdapter_Release(adapter
);
5936 swapchain_desc
.BufferDesc
.Width
= 800;
5937 swapchain_desc
.BufferDesc
.Height
= 600;
5938 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5939 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5940 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
5941 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5942 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5943 swapchain_desc
.SampleDesc
.Count
= 1;
5944 swapchain_desc
.SampleDesc
.Quality
= 0;
5945 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5946 swapchain_desc
.BufferCount
= 1;
5947 swapchain_desc
.OutputWindow
= window
;
5948 swapchain_desc
.Windowed
= TRUE
;
5949 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
5950 swapchain_desc
.Flags
= 0;
5952 /* create swapchain */
5954 expect_no_messages
= TRUE
;
5955 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
5956 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
5958 expect_no_messages
= FALSE
;
5961 expect_messages
= resize_target_messages
;
5962 memset(&mode_desc
, 0, sizeof(mode_desc
));
5963 mode_desc
.Width
= 800;
5964 mode_desc
.Height
= 600;
5965 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5966 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
5968 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5970 expect_messages
= resize_target_messages
;
5971 memset(&mode_desc
, 0, sizeof(mode_desc
));
5972 mode_desc
.Width
= 400;
5973 mode_desc
.Height
= 200;
5974 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5975 ok(hr
== S_OK
, "Failed to resize target, hr %#x.\n", hr
);
5977 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5979 /* enter fullscreen */
5980 expect_messages
= enter_fullscreen_messages
;
5981 expect_messages_broken
= enter_fullscreen_messages_vista
;
5982 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
5983 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
5984 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
5985 "Failed to enter fullscreen, hr %#x.\n", hr
);
5988 skip("Could not change fullscreen state.\n");
5993 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
5994 "Expected message %#x or %#x.\n",
5995 expect_messages
->message
, expect_messages_broken
->message
);
5996 expect_messages_broken
= NULL
;
5998 /* leave fullscreen */
5999 expect_messages
= leave_fullscreen_messages
;
6000 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6001 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6003 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
6004 expect_messages
= NULL
;
6006 refcount
= IDXGISwapChain_Release(swapchain
);
6007 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6009 /* create fullscreen swapchain */
6010 DestroyWindow(window
);
6011 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6012 ok(!!window
, "Failed to create window.\n");
6013 swapchain_desc
.OutputWindow
= window
;
6014 swapchain_desc
.Windowed
= FALSE
;
6015 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6018 expect_messages
= enter_fullscreen_messages
;
6019 expect_messages_broken
= enter_fullscreen_messages_vista
;
6020 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6021 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
6024 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
6025 "Expected message %#x or %#x.\n",
6026 expect_messages
->message
, expect_messages_broken
->message
);
6027 expect_messages_broken
= NULL
;
6029 /* leave fullscreen */
6030 expect_messages
= leave_fullscreen_messages
;
6031 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6032 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6034 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
6035 expect_messages
= NULL
;
6038 refcount
= IDXGISwapChain_Release(swapchain
);
6039 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6040 DestroyWindow(window
);
6042 refcount
= IDXGIDevice_Release(device
);
6043 ok(!refcount
, "Device has %u references left.\n", refcount
);
6044 refcount
= IDXGIFactory_Release(factory
);
6045 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6047 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
6050 static void test_swapchain_window_styles(void)
6052 LONG style
, exstyle
, fullscreen_style
, fullscreen_exstyle
;
6053 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6054 IDXGISwapChain
*swapchain
;
6055 IDXGIFactory
*factory
;
6056 IDXGIAdapter
*adapter
;
6057 IDXGIDevice
*device
;
6064 LONG style
, exstyle
;
6065 LONG expected_style
, expected_exstyle
;
6069 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
, 0,
6070 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
,
6072 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
, 0,
6073 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
| WS_VISIBLE
,
6075 {WS_OVERLAPPED
| WS_VISIBLE
, 0,
6076 WS_OVERLAPPED
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6077 {WS_OVERLAPPED
| WS_MAXIMIZE
, 0,
6078 WS_OVERLAPPED
| WS_MAXIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6079 {WS_OVERLAPPED
| WS_MINIMIZE
, 0,
6080 WS_OVERLAPPED
| WS_MINIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6081 {WS_CAPTION
| WS_DISABLED
, WS_EX_TOPMOST
,
6082 WS_CAPTION
| WS_DISABLED
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6083 {WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
, WS_EX_TOPMOST
,
6084 WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6085 {WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, WS_EX_APPWINDOW
,
6086 WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
},
6087 {WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6088 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6090 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6091 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6095 if (!(device
= create_device(0)))
6097 skip("Failed to create device.\n");
6101 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6102 ok(hr
== S_OK
, "Failed to get adapter, hr %#x.\n", hr
);
6103 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6104 ok(hr
== S_OK
, "Failed to get parent, hr %#x.\n", hr
);
6105 IDXGIAdapter_Release(adapter
);
6107 swapchain_desc
.BufferDesc
.Width
= 800;
6108 swapchain_desc
.BufferDesc
.Height
= 600;
6109 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6110 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6111 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6112 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6113 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6114 swapchain_desc
.SampleDesc
.Count
= 1;
6115 swapchain_desc
.SampleDesc
.Quality
= 0;
6116 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6117 swapchain_desc
.BufferCount
= 1;
6118 swapchain_desc
.Windowed
= TRUE
;
6119 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6120 swapchain_desc
.Flags
= 0;
6122 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6124 swapchain_desc
.OutputWindow
= CreateWindowExA(tests
[i
].exstyle
, "static", "dxgi_test",
6125 tests
[i
].style
, 0, 0, 400, 200, 0, 0, 0, 0);
6127 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6128 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6129 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6130 i
, style
, tests
[i
].expected_style
);
6131 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6132 i
, exstyle
, tests
[i
].expected_exstyle
);
6134 fullscreen_style
= tests
[i
].expected_style
& ~(WS_POPUP
| WS_MAXIMIZEBOX
6135 | WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_SYSMENU
| WS_DLGFRAME
| WS_BORDER
);
6136 fullscreen_exstyle
= tests
[i
].expected_exstyle
& ~(WS_EX_DLGMODALFRAME
6137 | WS_EX_TOOLWINDOW
| WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_CONTEXTHELP
);
6138 fullscreen_exstyle
|= WS_EX_TOPMOST
;
6140 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6141 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
6143 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6144 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6145 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6146 i
, style
, tests
[i
].expected_style
);
6147 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6148 i
, exstyle
, tests
[i
].expected_exstyle
);
6150 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6151 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6152 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6153 "Failed to set fullscreen state, hr %#x.\n", hr
);
6156 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6157 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6159 ok(style
== fullscreen_style
, "Test %u: Got style %#x, expected %#x.\n",
6160 i
, style
, fullscreen_style
);
6161 ok(exstyle
== fullscreen_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6162 i
, exstyle
, fullscreen_exstyle
);
6164 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6165 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6169 skip("Test %u: Could not change fullscreen state.\n", i
);
6172 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6173 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6174 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6175 i
, style
, tests
[i
].expected_style
);
6176 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6177 i
, exstyle
, tests
[i
].expected_exstyle
);
6179 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6180 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6181 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6182 "Failed to set fullscreen state, hr %#x.\n", hr
);
6185 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6186 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6188 ok(style
== fullscreen_style
, "Test %u: Got style %#x, expected %#x.\n",
6189 i
, style
, fullscreen_style
);
6190 ok(exstyle
== fullscreen_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6191 i
, exstyle
, fullscreen_exstyle
);
6193 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_STYLE
, fullscreen_style
);
6194 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
, fullscreen_exstyle
);
6196 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6197 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6199 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6200 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6202 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6203 i
, style
, tests
[i
].expected_style
);
6205 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6206 i
, exstyle
, tests
[i
].expected_exstyle
);
6210 skip("Test %u: Could not change fullscreen state.\n", i
);
6213 refcount
= IDXGISwapChain_Release(swapchain
);
6214 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6216 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6217 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6219 ok(style
== tests
[i
].expected_style
, "Test %u: Got style %#x, expected %#x.\n",
6220 i
, style
, tests
[i
].expected_style
);
6222 ok(exstyle
== tests
[i
].expected_exstyle
, "Test %u: Got exstyle %#x, expected %#x.\n",
6223 i
, exstyle
, tests
[i
].expected_exstyle
);
6225 DestroyWindow(swapchain_desc
.OutputWindow
);
6228 refcount
= IDXGIDevice_Release(device
);
6229 ok(!refcount
, "Device has %u references left.\n", refcount
);
6230 refcount
= IDXGIFactory_Release(factory
);
6231 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6234 static void test_gamma_control(void)
6236 DXGI_GAMMA_CONTROL_CAPABILITIES caps
;
6237 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6238 IDXGISwapChain
*swapchain
;
6239 DXGI_GAMMA_CONTROL gamma
;
6240 IDXGIFactory
*factory
;
6241 IDXGIAdapter
*adapter
;
6242 IDXGIDevice
*device
;
6243 IDXGIOutput
*output
;
6248 if (!(device
= create_device(0)))
6250 skip("Failed to create device.\n");
6254 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6255 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6257 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6258 if (hr
== DXGI_ERROR_NOT_FOUND
)
6260 skip("Adapter doesn't have any outputs.\n");
6261 IDXGIAdapter_Release(adapter
);
6262 IDXGIDevice_Release(device
);
6265 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6267 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6269 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6270 IDXGIOutput_Release(output
);
6272 swapchain_desc
.BufferDesc
.Width
= 640;
6273 swapchain_desc
.BufferDesc
.Height
= 480;
6274 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6275 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6276 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6277 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6278 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6279 swapchain_desc
.SampleDesc
.Count
= 1;
6280 swapchain_desc
.SampleDesc
.Quality
= 0;
6281 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6282 swapchain_desc
.BufferCount
= 1;
6283 swapchain_desc
.OutputWindow
= create_window();
6284 swapchain_desc
.Windowed
= TRUE
;
6285 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6286 swapchain_desc
.Flags
= 0;
6288 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6289 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6291 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6292 ok(hr
== S_OK
, "Failed to create swapchain, hr %#x.\n", hr
);
6293 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6294 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6295 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6296 "Failed to enter fullscreen, hr %#x.\n", hr
);
6299 skip("Could not change fullscreen state.\n");
6303 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
6304 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6306 memset(&caps
, 0, sizeof(caps
));
6307 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6308 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6310 ok(caps
.MaxConvertedValue
> caps
.MinConvertedValue
6311 || broken(caps
.MaxConvertedValue
== 0.0f
&& caps
.MinConvertedValue
== 1.0f
) /* WARP */,
6312 "Expected max gamma value (%.8e) to be bigger than min value (%.8e).\n",
6313 caps
.MaxConvertedValue
, caps
.MinConvertedValue
);
6315 for (i
= 1; i
< caps
.NumGammaControlPoints
; ++i
)
6317 ok(caps
.ControlPointPositions
[i
] > caps
.ControlPointPositions
[i
- 1],
6318 "Expected control point positions to be strictly monotonically increasing (%.8e > %.8e).\n",
6319 caps
.ControlPointPositions
[i
], caps
.ControlPointPositions
[i
- 1]);
6322 memset(&gamma
, 0, sizeof(gamma
));
6323 hr
= IDXGIOutput_GetGammaControl(output
, &gamma
);
6325 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6326 hr
= IDXGIOutput_SetGammaControl(output
, &gamma
);
6327 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6329 IDXGIOutput_Release(output
);
6331 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6332 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6335 refcount
= IDXGISwapChain_Release(swapchain
);
6336 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6337 DestroyWindow(swapchain_desc
.OutputWindow
);
6339 IDXGIAdapter_Release(adapter
);
6340 refcount
= IDXGIDevice_Release(device
);
6341 ok(!refcount
, "Device has %u references left.\n", refcount
);
6342 refcount
= IDXGIFactory_Release(factory
);
6343 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6346 static void test_window_association(IUnknown
*device
, BOOL is_d3d12
)
6348 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6349 LONG_PTR original_wndproc
, wndproc
;
6350 IDXGIFactory
*factory
, *factory2
;
6351 IDXGISwapChain
*swapchain
;
6352 IDXGIOutput
*output
;
6362 BOOL expect_fullscreen
;
6367 /* There are two reasons why VK_TAB and VK_ESC are not tested here:
6369 * - Posting them to the window doesn't exit fullscreen like
6370 * Alt+Enter does. Alt+Tab and Alt+Esc are handled somewhere else.
6371 * E.g., not calling IDXGISwapChain::Present() will break Alt+Tab
6372 * and Alt+Esc while Alt+Enter will still function.
6374 * - Posting them hangs the posting thread. Another thread that keeps
6375 * sending input is needed to avoid the hang. The hang is not
6376 * because of flush_events(). */
6379 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6380 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6381 {DXGI_MWA_NO_ALT_ENTER
, FALSE
, TRUE
},
6382 {DXGI_MWA_NO_ALT_ENTER
, FALSE
},
6383 {DXGI_MWA_NO_PRINT_SCREEN
, TRUE
},
6384 {DXGI_MWA_NO_PRINT_SCREEN
, FALSE
},
6389 swapchain_desc
.BufferDesc
.Width
= 640;
6390 swapchain_desc
.BufferDesc
.Height
= 480;
6391 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6392 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6393 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6394 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6395 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6396 swapchain_desc
.SampleDesc
.Count
= 1;
6397 swapchain_desc
.SampleDesc
.Quality
= 0;
6398 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6399 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6400 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6401 swapchain_desc
.Windowed
= TRUE
;
6402 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6403 swapchain_desc
.Flags
= 0;
6405 original_wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6407 hwnd2
= CreateWindowA("static", "dxgi_test2", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6408 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory2
);
6409 ok(hr
== S_OK
, "Failed to create DXGI factory, hr %#x.\n", hr
);
6411 get_factory(device
, is_d3d12
, &factory
);
6413 hr
= IDXGIFactory_GetWindowAssociation(factory
, NULL
);
6414 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6416 for (i
= 0; i
<= DXGI_MWA_VALID
; ++i
)
6418 hr
= IDXGIFactory_MakeWindowAssociation(factory
, NULL
, i
);
6419 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6421 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, i
);
6422 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6424 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6425 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#lx, expected %#lx for flags %#x.\n",
6426 wndproc
, original_wndproc
, i
);
6428 hwnd
= (HWND
)0xdeadbeef;
6429 hr
= IDXGIFactory_GetWindowAssociation(factory
, &hwnd
);
6430 ok(hr
== S_OK
, "Got unexpected hr %#x for flags %#x.\n", hr
, i
);
6431 /* Apparently GetWindowAssociation() always returns NULL, even when
6432 * MakeWindowAssociation() and GetWindowAssociation() are both
6433 * successfully called. */
6434 ok(!hwnd
, "Expect null associated window.\n");
6437 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, DXGI_MWA_VALID
+ 1);
6438 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6440 /* Alt+Enter tests. */
6441 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6442 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6444 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6445 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#lx, expected %#lx.\n", wndproc
, original_wndproc
);
6447 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6448 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6449 || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Windows 7 testbot */,
6450 "Got unexpected hr %#x.\n", hr
);
6453 skip("Could not change fullscreen state.\n");
6457 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6458 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6460 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6462 /* First associate a window with the opposite flags. */
6463 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6464 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6466 /* Associate the current test window. */
6467 hwnd
= tests
[i
].flag
? swapchain_desc
.OutputWindow
: NULL
;
6468 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd
, tests
[i
].flag
);
6469 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6471 /* Associating a new test window doesn't override the old window. */
6472 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6473 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6475 /* Associations with a different factory don't affect the existing
6477 hr
= IDXGIFactory_MakeWindowAssociation(factory2
, hwnd
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6478 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6480 /* Post synthesized Alt + VK_RETURN WM_SYSKEYDOWN. */
6481 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
6482 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
6485 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
6486 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#x.\n", i
, hr
);
6487 ok(fullscreen
== tests
[i
].expect_fullscreen
6488 || broken(tests
[i
].broken_d3d10
&& fullscreen
),
6489 "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
6490 ok(fullscreen
? !!output
: !output
, "Test %u: Got wrong output.\n", i
);
6492 IDXGIOutput_Release(output
);
6494 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6495 ok(wndproc
== original_wndproc
, "Test %u: Got unexpected wndproc %#lx, expected %#lx.\n",
6496 i
, wndproc
, original_wndproc
);
6500 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6501 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6503 refcount
= IDXGIFactory_Release(factory2
);
6504 ok(!refcount
, "Factory has %u references left.\n", refcount
);
6505 DestroyWindow(hwnd2
);
6507 refcount
= IDXGISwapChain_Release(swapchain
);
6508 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
6509 DestroyWindow(swapchain_desc
.OutputWindow
);
6511 refcount
= IDXGIFactory_Release(factory
);
6512 ok(refcount
== !is_d3d12
, "IDXGIFactory has %u references left.\n", refcount
);
6515 static void test_output_ownership(IUnknown
*device
, BOOL is_d3d12
)
6517 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc
;
6518 D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_ownership_desc
;
6519 D3DKMT_CLOSEADAPTER close_adapter_desc
;
6520 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6521 DXGI_OUTPUT_DESC output_desc
;
6522 IDXGISwapChain
*swapchain
;
6523 IDXGIFactory
*factory
;
6524 IDXGIAdapter
*adapter
;
6525 IDXGIOutput
*output
;
6531 if (!pD3DKMTCheckVidPnExclusiveOwnership
6532 || pD3DKMTCheckVidPnExclusiveOwnership(NULL
) == STATUS_PROCEDURE_NOT_FOUND
)
6534 win_skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n");
6538 get_factory(device
, is_d3d12
, &factory
);
6539 adapter
= get_adapter(device
, is_d3d12
);
6542 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
6543 IDXGIFactory_Release(factory
);
6547 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6548 IDXGIAdapter_Release(adapter
);
6549 if (hr
== DXGI_ERROR_NOT_FOUND
)
6551 skip("Adapter doesn't have any outputs.\n");
6552 IDXGIFactory_Release(factory
);
6555 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6557 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6558 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6560 lstrcpyW(open_adapter_gdi_desc
.DeviceName
, output_desc
.DeviceName
);
6561 status
= pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc
);
6562 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
6564 check_ownership_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6565 check_ownership_desc
.VidPnSourceId
= open_adapter_gdi_desc
.VidPnSourceId
;
6566 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6567 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6570 swapchain_desc
.BufferDesc
.Width
= 800;
6571 swapchain_desc
.BufferDesc
.Height
= 600;
6572 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6573 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6574 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6575 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6576 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6577 swapchain_desc
.SampleDesc
.Count
= 1;
6578 swapchain_desc
.SampleDesc
.Quality
= 0;
6579 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6580 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6581 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
6582 swapchain_desc
.Windowed
= TRUE
;
6583 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6584 swapchain_desc
.Flags
= 0;
6585 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6586 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6588 /* Swapchain in fullscreen mode. */
6589 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
6590 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
6591 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
6592 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
6594 skip("Failed to change fullscreen state.\n");
6597 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6599 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6600 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6601 ok(fullscreen
, "Got unexpected fullscreen state.\n");
6602 /* Win10 1909 doesn't seem to grab output exclusive ownership.
6603 * And all output ownership calls return S_OK on D3D10 and D3D12 with 1909. */
6606 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6607 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6612 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6613 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6614 todo_wine
ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6615 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6616 "Got unexpected status %#x, expected %#x.\n", status
,
6617 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6619 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, FALSE
);
6620 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6621 "Got unexpected hr %#x.\n", hr
);
6622 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, TRUE
);
6623 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6624 "Got unexpected hr %#x.\n", hr
);
6625 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6627 todo_wine
ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6629 todo_wine
ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
), /* Win10 1909 */
6630 "Got unexpected hr %#x.\n", hr
);
6631 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6632 ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6633 IDXGIOutput_ReleaseOwnership(output
);
6634 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6635 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6638 /* IDXGIOutput_TakeOwnership always returns E_NOINTERFACE for d3d12. Tests
6643 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6644 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6645 "Got unexpected hr %#x.\n", hr
);
6646 IDXGIOutput_ReleaseOwnership(output
);
6648 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6649 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6650 /* Note that the "exclusive" parameter to IDXGIOutput_TakeOwnership()
6651 * seems to behave opposite to what's described by MSDN. */
6652 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6653 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6654 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6655 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6656 "Got unexpected status %#x, expected %#x.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6657 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6658 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Win10 1909 */, "Got unexpected hr %#x.\n", hr
);
6659 IDXGIOutput_ReleaseOwnership(output
);
6661 /* Swapchain in windowed mode. */
6662 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6663 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6665 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6666 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6667 ok(!fullscreen
, "Unexpected fullscreen state.\n");
6668 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6669 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6672 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6673 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6674 "Got unexpected hr %#x.\n", hr
);
6676 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6677 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6678 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6679 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6680 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
|| broken(hr
== S_OK
), /* Win10 1909 */
6681 "Got unexpected status %#x, expected %#x.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6682 IDXGIOutput_ReleaseOwnership(output
);
6683 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6684 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x, expected %#x.\n", status
,
6688 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6689 wait_device_idle(device
);
6691 IDXGIOutput_Release(output
);
6692 IDXGISwapChain_Release(swapchain
);
6693 DestroyWindow(swapchain_desc
.OutputWindow
);
6694 refcount
= IDXGIFactory_Release(factory
);
6695 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
6697 close_adapter_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6698 status
= pD3DKMTCloseAdapter(&close_adapter_desc
);
6699 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#x.\n", status
);
6702 static void test_cursor_clipping(IUnknown
*device
, BOOL is_d3d12
)
6704 unsigned int adapter_idx
, output_idx
, mode_idx
, mode_count
;
6705 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6706 DXGI_OUTPUT_DESC output_desc
;
6707 IDXGIAdapter
*adapter
= NULL
;
6708 RECT virtual_rect
, clip_rect
;
6709 unsigned int width
, height
;
6710 IDXGISwapChain
*swapchain
;
6711 DXGI_MODE_DESC
*modes
;
6712 IDXGIFactory
*factory
;
6713 IDXGIOutput
*output
;
6718 get_factory(device
, is_d3d12
, &factory
);
6720 swapchain_desc
.SampleDesc
.Count
= 1;
6721 swapchain_desc
.SampleDesc
.Quality
= 0;
6722 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6723 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6724 swapchain_desc
.Windowed
= TRUE
;
6725 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6726 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6728 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
6731 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
6734 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
,
6736 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 TestBots */
6737 "Adapter %u output %u: GetDisplayModeList failed, hr %#x.\n", adapter_idx
,
6739 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
6741 win_skip("Adapter %u output %u: GetDisplayModeList() not supported.\n", adapter_idx
,
6743 IDXGIOutput_Release(output
);
6747 modes
= heap_calloc(mode_count
, sizeof(*modes
));
6748 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
,
6750 ok(hr
== S_OK
, "Adapter %u output %u: GetDisplayModeList failed, hr %#x.\n",
6751 adapter_idx
, output_idx
, hr
);
6753 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6754 ok(hr
== S_OK
, "Adapter %u output %u: GetDesc failed, hr %#x.\n", adapter_idx
,
6756 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
6757 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
6758 for (mode_idx
= 0; mode_idx
< mode_count
; ++mode_idx
)
6760 if (modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
)
6763 ok(modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
,
6764 "Adapter %u output %u: Failed to find a different mode than %ux%u.\n",
6765 adapter_idx
, output_idx
, width
, height
);
6767 ret
= ClipCursor(NULL
);
6768 ok(ret
, "Adapter %u output %u: ClipCursor failed, error %#x.\n",
6769 adapter_idx
, output_idx
, GetLastError());
6770 get_virtual_rect(&virtual_rect
);
6771 ret
= GetClipCursor(&clip_rect
);
6772 ok(ret
, "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6773 output_idx
, GetLastError());
6774 ok(EqualRect(&clip_rect
, &virtual_rect
),
6775 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6776 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6778 swapchain_desc
.BufferDesc
.Width
= modes
[mode_idx
].Width
;
6779 swapchain_desc
.BufferDesc
.Height
= modes
[mode_idx
].Height
;
6780 swapchain_desc
.BufferDesc
.RefreshRate
= modes
[mode_idx
].RefreshRate
;
6781 swapchain_desc
.BufferDesc
.Format
= modes
[mode_idx
].Format
;
6782 swapchain_desc
.BufferDesc
.ScanlineOrdering
= modes
[mode_idx
].ScanlineOrdering
;
6783 swapchain_desc
.BufferDesc
.Scaling
= modes
[mode_idx
].Scaling
;
6784 swapchain_desc
.OutputWindow
= create_window();
6786 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6787 ok(hr
== S_OK
, "Adapter %u output %u: CreateSwapChain failed, hr %#x.\n",
6788 adapter_idx
, output_idx
, hr
);
6791 get_virtual_rect(&virtual_rect
);
6792 ret
= GetClipCursor(&clip_rect
);
6793 ok(ret
, "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6794 output_idx
, GetLastError());
6795 ok(EqualRect(&clip_rect
, &virtual_rect
),
6796 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6797 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6799 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6800 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
||
6801 broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6802 "Adapter %u output %u: SetFullscreenState failed, hr %#x.\n", adapter_idx
,
6806 skip("Adapter %u output %u: Could not change fullscreen state, hr %#x.\n",
6807 adapter_idx
, output_idx
, hr
);
6808 IDXGISwapChain_Release(swapchain
);
6809 IDXGIOutput_Release(output
);
6810 DestroyWindow(swapchain_desc
.OutputWindow
);
6815 get_virtual_rect(&virtual_rect
);
6816 ret
= GetClipCursor(&clip_rect
);
6817 ok(ret
, "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6818 output_idx
, GetLastError());
6819 ok(EqualRect(&clip_rect
, &virtual_rect
),
6820 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6821 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6823 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6824 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_idx
,
6826 refcount
= IDXGISwapChain_Release(swapchain
);
6827 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %u references left.\n",
6828 adapter_idx
, output_idx
, refcount
);
6829 refcount
= IDXGIOutput_Release(output
);
6830 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %u references left.\n",
6831 adapter_idx
, output_idx
, refcount
);
6832 DestroyWindow(swapchain_desc
.OutputWindow
);
6835 get_virtual_rect(&virtual_rect
);
6836 ret
= GetClipCursor(&clip_rect
);
6837 ok(ret
, "Adapter %u output %u: GetClipCursor failed, error %#x.\n", adapter_idx
,
6838 output_idx
, GetLastError());
6839 ok(EqualRect(&clip_rect
, &virtual_rect
),
6840 "Adapter %u output %u: Expect clip rect %s, got %s.\n", adapter_idx
, output_idx
,
6841 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6844 IDXGIAdapter_Release(adapter
);
6847 refcount
= IDXGIFactory_Release(factory
);
6848 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
6851 static void test_factory_check_feature_support(void)
6853 IDXGIFactory5
*factory
;
6858 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory5
, (void**)&factory
)))
6860 win_skip("IDXGIFactory5 is not available.\n");
6864 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, 0x12345678, (void *)&data
, sizeof(data
));
6865 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6867 /* Crashes on Windows. */
6870 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, NULL
, sizeof(data
));
6871 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6874 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) - 1);
6875 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6877 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) + 1);
6878 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6880 data
= (BOOL
)0xdeadbeef;
6881 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
));
6882 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6883 ok(data
== TRUE
|| data
== FALSE
, "Got unexpected data %#x.\n", data
);
6885 ref_count
= IDXGIFactory5_Release(factory
);
6886 ok(!ref_count
, "Factory has %u references left.\n", ref_count
);
6889 static void test_frame_latency_event(IUnknown
*device
, BOOL is_d3d12
)
6891 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
6892 IDXGISwapChain2
*swapchain2
;
6893 IDXGISwapChain1
*swapchain1
;
6894 IDXGIFactory2
*factory2
;
6895 IDXGIFactory
*factory
;
6904 get_factory(device
, is_d3d12
, &factory
);
6906 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
6907 IDXGIFactory_Release(factory
);
6910 win_skip("IDXGIFactory2 not available.\n");
6914 window
= create_window();
6916 swapchain_desc
.Width
= 640;
6917 swapchain_desc
.Height
= 480;
6918 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6919 swapchain_desc
.Stereo
= FALSE
;
6920 swapchain_desc
.SampleDesc
.Count
= 1;
6921 swapchain_desc
.SampleDesc
.Quality
= 0;
6922 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6923 swapchain_desc
.BufferCount
= 2;
6924 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
6925 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
6926 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
6927 swapchain_desc
.Flags
= 0;
6929 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6930 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6931 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6933 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6934 IDXGISwapChain1_Release(swapchain1
);
6937 win_skip("IDXGISwapChain2 not available.\n");
6938 IDXGIFactory2_Release(factory2
);
6939 DestroyWindow(window
);
6943 /* test swap chain without waitable object */
6944 frame_latency
= 0xdeadbeef;
6945 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6946 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6947 ok(frame_latency
== 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency
);
6948 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 1);
6949 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6950 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6951 ok(!event
, "Got unexpected event %p.\n", event
);
6953 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6954 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
6956 /* test swap chain with waitable object */
6957 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
;
6959 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6960 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6961 ok(hr
== S_OK
, "Failed to create swap chain, hr %#x.\n", hr
);
6962 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6963 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6964 IDXGISwapChain1_Release(swapchain1
);
6966 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6967 ok(!!event
, "Got unexpected event %p.\n", event
);
6969 /* auto-reset event */
6970 wait_result
= WaitForSingleObject(event
, 0);
6971 ok(!wait_result
, "Got unexpected wait result %#x.\n", wait_result
);
6972 wait_result
= WaitForSingleObject(event
, 0);
6973 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#x.\n", wait_result
);
6975 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6976 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6977 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6979 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 0);
6980 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
6981 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6982 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6983 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6985 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 2);
6986 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6987 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6988 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
6989 ok(frame_latency
== 2, "Got unexpected frame latency %#x.\n", frame_latency
);
6991 for (i
= 0; i
< 5; i
++)
6993 hr
= IDXGISwapChain2_Present(swapchain2
, 0, 0);
6994 ok(hr
== S_OK
, "Present %u failed with hr %#x.\n", i
, hr
);
6997 wait_result
= WaitForSingleObject(event
, 1000);
6998 ok(!wait_result
, "Got unexpected wait result %#x.\n", wait_result
);
7000 ref_count
= IDXGISwapChain2_Release(swapchain2
);
7001 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
7002 DestroyWindow(window
);
7003 ref_count
= IDXGIFactory2_Release(factory2
);
7004 ok(ref_count
== !is_d3d12
, "Factory has %u references left.\n", ref_count
);
7007 static void test_colour_space_support(IUnknown
*device
, BOOL is_d3d12
)
7009 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
7010 IDXGISwapChain3
*swapchain3
;
7011 IDXGISwapChain1
*swapchain1
;
7012 IDXGIFactory2
*factory2
;
7013 IDXGIFactory
*factory
;
7020 static const DXGI_COLOR_SPACE_TYPE colour_spaces
[] =
7022 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
,
7023 DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
,
7024 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
,
7025 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
,
7026 DXGI_COLOR_SPACE_RESERVED
,
7027 DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
,
7028 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
,
7029 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
,
7030 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
,
7031 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
,
7032 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
,
7033 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
,
7034 DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
,
7035 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
,
7036 DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
,
7037 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
,
7038 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
,
7039 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
,
7040 DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
,
7041 DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
,
7044 get_factory(device
, is_d3d12
, &factory
);
7046 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
7047 IDXGIFactory_Release(factory
);
7050 win_skip("IDXGIFactory2 not available.\n");
7054 window
= create_window();
7056 swapchain_desc
.Width
= 640;
7057 swapchain_desc
.Height
= 480;
7058 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7059 swapchain_desc
.Stereo
= FALSE
;
7060 swapchain_desc
.SampleDesc
.Count
= 1;
7061 swapchain_desc
.SampleDesc
.Quality
= 0;
7062 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7063 swapchain_desc
.BufferCount
= 2;
7064 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
7065 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
7066 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
7067 swapchain_desc
.Flags
= 0;
7069 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
7070 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
7071 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7073 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain3
, (void**)&swapchain3
);
7074 IDXGISwapChain1_Release(swapchain1
);
7077 win_skip("IDXGISwapChain3 not available.\n");
7078 IDXGIFactory2_Release(factory2
);
7079 DestroyWindow(window
);
7083 for (i
= 0; i
< ARRAY_SIZE(colour_spaces
); ++i
)
7085 support
= 0xdeadbeef;
7086 hr
= IDXGISwapChain3_CheckColorSpaceSupport(swapchain3
, colour_spaces
[i
], &support
);
7087 ok(hr
== S_OK
, "Got unexpected hr %#x for test %u.\n", hr
, i
);
7088 ok(!(support
& ~DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
),
7089 "Got unexpected support flags %#x for test %u.\n", support
, i
);
7091 if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
)
7093 ok(support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
,
7094 "Required colour space not supported for test %u.\n", i
);
7096 else if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RESERVED
)
7098 ok(!support
, "Invalid colour space supported for test %u.\n", i
);
7101 hr
= IDXGISwapChain3_SetColorSpace1(swapchain3
, colour_spaces
[i
]);
7102 ok(hr
== (support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
) ? S_OK
: E_INVALIDARG
,
7103 "Got unexpected hr %#x for text %u.\n", hr
, i
);
7106 ref_count
= IDXGISwapChain3_Release(swapchain3
);
7107 ok(!ref_count
, "Swap chain has %u references left.\n", ref_count
);
7108 DestroyWindow(window
);
7109 ref_count
= IDXGIFactory2_Release(factory2
);
7110 ok(ref_count
== !is_d3d12
, "Factory has %u references left.\n", ref_count
);
7113 static void test_mode_change(IUnknown
*device
, BOOL is_d3d12
)
7115 unsigned int user32_width
= 0, user32_height
= 0, d3d_width
= 0, d3d_height
= 0;
7116 unsigned int display_count
= 0, mode_idx
= 0, adapter_idx
, output_idx
;
7117 DEVMODEW
*original_modes
= NULL
, old_devmode
, devmode
, devmode2
;
7118 DXGI_SWAP_CHAIN_DESC swapchain_desc
, swapchain_desc2
;
7119 IDXGIOutput
*output
, *second_output
= NULL
;
7120 WCHAR second_monitor_name
[CCHDEVICENAME
];
7121 IDXGISwapChain
*swapchain
, *swapchain2
;
7122 DXGI_OUTPUT_DESC output_desc
;
7123 IDXGIAdapter
*adapter
;
7124 IDXGIFactory
*factory
;
7125 BOOL fullscreen
, ret
;
7130 memset(&devmode
, 0, sizeof(devmode
));
7131 devmode
.dmSize
= sizeof(devmode
);
7132 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode
);
7133 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7134 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7135 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode
);
7136 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7137 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7139 while (EnumDisplaySettingsW(NULL
, mode_idx
++, &devmode
))
7141 if (devmode
.dmPelsWidth
== registry_mode
.dmPelsWidth
7142 && devmode
.dmPelsHeight
== registry_mode
.dmPelsHeight
)
7145 if (!d3d_width
&& !d3d_height
)
7147 d3d_width
= devmode
.dmPelsWidth
;
7148 d3d_height
= devmode
.dmPelsHeight
;
7152 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7155 user32_width
= devmode
.dmPelsWidth
;
7156 user32_height
= devmode
.dmPelsHeight
;
7159 if (!user32_width
|| !user32_height
)
7161 skip("Failed to find three different display modes for the primary output.\n");
7165 ret
= save_display_modes(&original_modes
, &display_count
);
7166 ok(ret
, "Failed to save original display modes.\n");
7168 get_factory(device
, is_d3d12
, &factory
);
7170 /* Test that no mode restorations if no mode changes actually happened */
7171 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7172 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7174 swapchain_desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
7175 swapchain_desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
7176 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
7177 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
7178 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7179 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
7180 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
7181 swapchain_desc
.SampleDesc
.Count
= 1;
7182 swapchain_desc
.SampleDesc
.Quality
= 0;
7183 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7184 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
7185 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
7186 swapchain_desc
.Windowed
= TRUE
;
7187 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
7188 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
7190 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7191 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7192 refcount
= IDXGISwapChain_Release(swapchain
);
7193 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7195 memset(&devmode2
, 0, sizeof(devmode2
));
7196 devmode2
.dmSize
= sizeof(devmode2
);
7197 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7198 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7199 ok(equal_mode_rect(&devmode2
, ®istry_mode
), "Got a different mode.\n");
7200 ret
= restore_display_modes(original_modes
, display_count
);
7201 ok(ret
, "Failed to restore display modes.\n");
7203 /* If current display settings are different than the display settings in registry before
7204 * calling SetFullscreenState() */
7205 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7206 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7208 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7209 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7210 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7211 ok(hr
== DXGI_ERROR_UNSUPPORTED
/* Win7 */
7212 || hr
== S_OK
/* Win8~Win10 1909 */
7213 || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, /* Win10 2004 */
7214 "Got unexpected hr %#x.\n", hr
);
7216 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7217 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7218 refcount
= IDXGISwapChain_Release(swapchain
);
7219 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7220 ret
= restore_display_modes(original_modes
, display_count
);
7221 ok(ret
, "Failed to restore display modes.\n");
7223 /* Test that mode restorations use display settings in the registry with a fullscreen device */
7224 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7225 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7226 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7229 skip("SetFullscreenState failed, hr %#x.\n", hr
);
7230 refcount
= IDXGISwapChain_Release(swapchain
);
7231 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7235 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7236 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %d.\n", change_ret
);
7237 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7238 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7240 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7241 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7242 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7243 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7244 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7245 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7246 refcount
= IDXGISwapChain_Release(swapchain
);
7247 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7248 ret
= restore_display_modes(original_modes
, display_count
);
7249 ok(ret
, "Failed to restore display modes.\n");
7251 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
)); ++adapter_idx
)
7253 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
)); ++output_idx
)
7255 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
7256 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#x.\n", adapter_idx
, output_idx
, hr
);
7258 if ((adapter_idx
|| output_idx
) && output_desc
.AttachedToDesktop
)
7260 second_output
= output
;
7264 IDXGIOutput_Release(output
);
7267 IDXGIAdapter_Release(adapter
);
7274 skip("Following tests require two monitors.\n");
7277 lstrcpyW(second_monitor_name
, output_desc
.DeviceName
);
7279 memset(&old_devmode
, 0, sizeof(old_devmode
));
7280 old_devmode
.dmSize
= sizeof(old_devmode
);
7281 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &old_devmode
);
7282 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7289 while (EnumDisplaySettingsW(second_monitor_name
, mode_idx
++, &devmode
))
7291 if (devmode
.dmPelsWidth
== old_devmode
.dmPelsWidth
7292 && devmode
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7295 if (!d3d_width
&& !d3d_height
)
7297 d3d_width
= devmode
.dmPelsWidth
;
7298 d3d_height
= devmode
.dmPelsHeight
;
7302 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7305 user32_width
= devmode
.dmPelsWidth
;
7306 user32_height
= devmode
.dmPelsHeight
;
7309 if (!user32_width
|| !user32_height
)
7311 skip("Failed to find three different display modes for the second output.\n");
7315 /* Test that mode restorations for non-primary outputs upon fullscreen state changes */
7316 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7317 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7318 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7319 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7321 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
, CDS_RESET
, NULL
);
7322 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %d.\n", change_ret
);
7323 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7324 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7325 if (devmode2
.dmPelsWidth
== old_devmode
.dmPelsWidth
7326 && devmode2
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7328 skip("Failed to change display settings of the second monitor.\n");
7329 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7330 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7331 refcount
= IDXGISwapChain_Release(swapchain
);
7332 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7336 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7337 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7339 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7340 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7341 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7342 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7343 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7344 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7345 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7346 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7347 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7348 old_devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", old_devmode
.dmPelsWidth
,
7349 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7350 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7351 old_devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", old_devmode
.dmPelsHeight
,
7352 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7354 refcount
= IDXGISwapChain_Release(swapchain
);
7355 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7356 ret
= restore_display_modes(original_modes
, display_count
);
7357 ok(ret
, "Failed to restore display modes.\n");
7359 /* Test that mode restorations for non-primary outputs use display settings in the registry */
7360 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7361 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7362 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7363 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7365 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
,
7366 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
7367 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %d.\n", change_ret
);
7368 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7369 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7371 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7372 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7373 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7374 "Expected resolution %ux%u, got %ux%u.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7375 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7376 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7377 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7378 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7379 "Expected resolution %ux%u, got %ux%u.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7380 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7381 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7382 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7383 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7384 devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", devmode
.dmPelsWidth
,
7385 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7386 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7387 devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", devmode
.dmPelsHeight
,
7388 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7390 refcount
= IDXGISwapChain_Release(swapchain
);
7391 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7392 ret
= restore_display_modes(original_modes
, display_count
);
7393 ok(ret
, "Failed to restore display modes.\n");
7395 /* Test that mode restorations for non-primary outputs on fullscreen state changes when there
7396 * are two fullscreen swapchains on different outputs */
7397 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7398 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7400 swapchain_desc2
= swapchain_desc
;
7401 swapchain_desc
.BufferDesc
.Width
= d3d_width
;
7402 swapchain_desc
.BufferDesc
.Height
= d3d_height
;
7403 swapchain_desc2
.OutputWindow
= CreateWindowA("static", "dxgi_test2", 0,
7404 old_devmode
.dmPosition
.x
, old_devmode
.dmPosition
.y
, 400, 200, 0, 0, 0, 0);
7405 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc2
, &swapchain2
);
7406 ok(hr
== S_OK
, "CreateSwapChain failed, hr %#x.\n", hr
);
7407 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7408 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7409 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, TRUE
, NULL
);
7412 skip("SetFullscreenState failed, hr %#x.\n", hr
);
7413 refcount
= IDXGISwapChain_Release(swapchain2
);
7414 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7415 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7416 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7417 refcount
= IDXGISwapChain_Release(swapchain
);
7418 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7422 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7423 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7424 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
7425 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
7426 ok(!fullscreen
, "Expected swapchain not fullscreen.\n");
7427 hr
= IDXGISwapChain_GetFullscreenState(swapchain2
, &fullscreen
, NULL
);
7428 ok(hr
== S_OK
, "GetFullscreenState failed, hr %#x.\n", hr
);
7429 ok(fullscreen
, "Expected swapchain fullscreen.\n");
7431 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7432 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7433 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7434 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7435 ok(ret
, "EnumDisplaySettingsW failed, error %#x.\n", GetLastError());
7436 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7437 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7438 ok(hr
== S_OK
, "GetDesc failed, hr %#x.\n", hr
);
7439 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7440 old_devmode
.dmPelsWidth
, "Expected width %u, got %u.\n", old_devmode
.dmPelsWidth
,
7441 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7442 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7443 old_devmode
.dmPelsHeight
, "Expected height %u, got %u.\n", old_devmode
.dmPelsHeight
,
7444 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7446 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, FALSE
, NULL
);
7447 ok(hr
== S_OK
, "SetFullscreenState failed, hr %#x.\n", hr
);
7448 refcount
= IDXGISwapChain_Release(swapchain2
);
7449 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7450 refcount
= IDXGISwapChain_Release(swapchain
);
7451 ok(!refcount
, "IDXGISwapChain has %u references left.\n", refcount
);
7452 DestroyWindow(swapchain_desc2
.OutputWindow
);
7453 ret
= restore_display_modes(original_modes
, display_count
);
7454 ok(ret
, "Failed to restore display modes.\n");
7458 IDXGIOutput_Release(second_output
);
7459 DestroyWindow(swapchain_desc
.OutputWindow
);
7460 refcount
= IDXGIFactory_Release(factory
);
7461 ok(refcount
== !is_d3d12
, "Got unexpected refcount %u.\n", refcount
);
7462 ret
= restore_display_modes(original_modes
, display_count
);
7463 ok(ret
, "Failed to restore display modes.\n");
7464 heap_free(original_modes
);
7467 static void test_swapchain_present_count(IUnknown
*device
, BOOL is_d3d12
)
7469 UINT present_count
, expected
;
7470 IDXGISwapChain
*swapchain
;
7474 window
= create_window();
7475 swapchain
= create_swapchain(device
, is_d3d12
, window
);
7477 present_count
= ~0u;
7478 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7479 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7480 todo_wine_if(is_d3d12
) ok(!present_count
, "Got unexpected present count %u.\n", present_count
);
7482 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7483 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7484 expected
= present_count
+ 1;
7485 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7486 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7487 todo_wine_if(is_d3d12
)
7488 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7490 hr
= IDXGISwapChain_Present(swapchain
, 10, 0);
7491 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#x.\n", hr
);
7492 expected
= present_count
;
7493 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7494 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7495 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7497 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
7498 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7499 expected
= present_count
;
7500 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7501 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7502 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7504 ShowWindow(window
, SW_MINIMIZE
);
7505 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7506 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Got unexpected hr %#x.\n", hr
);
7507 expected
= present_count
+ !!is_d3d12
;
7508 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7509 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7510 todo_wine_if(is_d3d12
)
7511 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7513 ShowWindow(window
, SW_NORMAL
);
7514 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7515 ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7516 expected
= present_count
+ 1;
7517 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7518 todo_wine_if(is_d3d12
) ok(hr
== S_OK
, "Got unexpected hr %#x.\n", hr
);
7519 todo_wine_if(is_d3d12
)
7520 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7522 IDXGISwapChain_Release(swapchain
);
7523 DestroyWindow(window
);
7526 static void run_on_d3d10(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7528 IDXGIDevice
*device
;
7531 if (!(device
= create_device(0)))
7533 skip("Failed to create Direct3D 10 device.\n");
7537 test_func((IUnknown
*)device
, FALSE
);
7539 refcount
= IDXGIDevice_Release(device
);
7540 ok(!refcount
, "Device has %u references left.\n", refcount
);
7543 static void run_on_d3d12(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7545 ID3D12CommandQueue
*queue
;
7546 ID3D12Device
*device
;
7549 if (!(device
= create_d3d12_device()))
7551 skip("Failed to create Direct3D 12 device.\n");
7555 queue
= create_d3d12_direct_queue(device
);
7557 test_func((IUnknown
*)queue
, TRUE
);
7559 wait_queue_idle(device
, queue
);
7561 refcount
= ID3D12CommandQueue_Release(queue
);
7562 ok(!refcount
, "Command queue has %u references left.\n", refcount
);
7563 refcount
= ID3D12Device_Release(device
);
7564 ok(!refcount
, "Device has %u references left.\n", refcount
);
7569 HMODULE dxgi_module
, d3d11_module
, d3d12_module
, gdi32_module
;
7570 BOOL enable_debug_layer
= FALSE
;
7571 unsigned int argc
, i
;
7575 dxgi_module
= GetModuleHandleA("dxgi.dll");
7576 pCreateDXGIFactory1
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory1");
7577 pCreateDXGIFactory2
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory2");
7579 gdi32_module
= GetModuleHandleA("gdi32.dll");
7580 pD3DKMTCheckVidPnExclusiveOwnership
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCheckVidPnExclusiveOwnership");
7581 pD3DKMTCloseAdapter
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCloseAdapter");
7582 pD3DKMTOpenAdapterFromGdiDisplayName
= (void *)GetProcAddress(gdi32_module
, "D3DKMTOpenAdapterFromGdiDisplayName");
7584 d3d11_module
= LoadLibraryA("d3d11.dll");
7585 pD3D11CreateDevice
= (void *)GetProcAddress(d3d11_module
, "D3D11CreateDevice");
7587 registry_mode
.dmSize
= sizeof(registry_mode
);
7588 ok(EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, ®istry_mode
), "Failed to get display mode.\n");
7590 use_mt
= !getenv("WINETEST_NO_MT_D3D");
7592 argc
= winetest_get_mainargs(&argv
);
7593 for (i
= 2; i
< argc
; ++i
)
7595 if (!strcmp(argv
[i
], "--validate"))
7596 enable_debug_layer
= TRUE
;
7597 else if (!strcmp(argv
[i
], "--warp"))
7598 use_warp_adapter
= TRUE
;
7599 else if (!strcmp(argv
[i
], "--adapter") && i
+ 1 < argc
)
7600 use_adapter_idx
= atoi(argv
[++i
]);
7601 else if (!strcmp(argv
[i
], "--single"))
7605 queue_test(test_adapter_desc
);
7606 queue_test(test_adapter_luid
);
7607 queue_test(test_query_video_memory_info
);
7608 queue_test(test_check_interface_support
);
7609 queue_test(test_create_surface
);
7610 queue_test(test_parents
);
7611 queue_test(test_output
);
7612 queue_test(test_find_closest_matching_mode
);
7613 queue_test(test_resize_target_wndproc
);
7614 queue_test(test_create_factory
);
7615 queue_test(test_private_data
);
7616 queue_test(test_maximum_frame_latency
);
7617 queue_test(test_output_desc
);
7618 queue_test(test_object_wrapping
);
7619 queue_test(test_factory_check_feature_support
);
7623 /* These tests use full-screen swapchains, so shouldn't run in parallel. */
7624 test_create_swapchain();
7625 test_inexact_modes();
7626 test_gamma_control();
7627 test_multi_adapter();
7628 test_swapchain_parameters();
7629 test_swapchain_window_messages();
7630 test_swapchain_window_styles();
7631 run_on_d3d10(test_set_fullscreen
);
7632 run_on_d3d10(test_resize_target
);
7633 run_on_d3d10(test_swapchain_resize
);
7634 run_on_d3d10(test_swapchain_present
);
7635 run_on_d3d10(test_swapchain_backbuffer_index
);
7636 run_on_d3d10(test_swapchain_formats
);
7637 run_on_d3d10(test_output_ownership
);
7638 run_on_d3d10(test_cursor_clipping
);
7639 run_on_d3d10(test_get_containing_output
);
7640 run_on_d3d10(test_window_association
);
7641 run_on_d3d10(test_default_fullscreen_target_output
);
7642 run_on_d3d10(test_mode_change
);
7643 run_on_d3d10(test_swapchain_present_count
);
7645 if (!(d3d12_module
= LoadLibraryA("d3d12.dll")))
7647 skip("Direct3D 12 is not available.\n");
7651 pD3D12CreateDevice
= (void *)GetProcAddress(d3d12_module
, "D3D12CreateDevice");
7652 pD3D12GetDebugInterface
= (void *)GetProcAddress(d3d12_module
, "D3D12GetDebugInterface");
7654 if (enable_debug_layer
&& SUCCEEDED(pD3D12GetDebugInterface(&IID_ID3D12Debug
, (void **)&debug
)))
7656 ID3D12Debug_EnableDebugLayer(debug
);
7657 ID3D12Debug_Release(debug
);
7660 run_on_d3d12(test_set_fullscreen
);
7661 run_on_d3d12(test_resize_target
);
7662 run_on_d3d12(test_swapchain_resize
);
7663 run_on_d3d12(test_swapchain_present
);
7664 run_on_d3d12(test_swapchain_backbuffer_index
);
7665 run_on_d3d12(test_swapchain_formats
);
7666 run_on_d3d12(test_output_ownership
);
7667 run_on_d3d12(test_cursor_clipping
);
7668 run_on_d3d12(test_frame_latency_event
);
7669 run_on_d3d12(test_colour_space_support
);
7670 run_on_d3d12(test_get_containing_output
);
7671 run_on_d3d12(test_window_association
);
7672 run_on_d3d12(test_default_fullscreen_target_output
);
7673 run_on_d3d12(test_mode_change
);
7674 run_on_d3d12(test_swapchain_present_count
);
7676 FreeLibrary(d3d12_module
);