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 unexpected hr %#lx, expected %#lx.\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
, "Got unexpected hr %#lx.\n", hr
);
270 hr
= ID3D10Device_CheckMultisampleQualityLevels(device
, format
, sample_count
, &levels
);
271 ok(hr
== S_OK
, "Got unexpected hr %#lx.\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 %Iu, expected %Iu.\n",
357 desc
->DedicatedVideoMemory
, expected_desc
->DedicatedVideoMemory
);
358 ok_(__FILE__
, line
)(desc
->DedicatedSystemMemory
== expected_desc
->DedicatedSystemMemory
,
359 "Got dedicated system memory %Iu, expected %Iu.\n",
360 desc
->DedicatedSystemMemory
, expected_desc
->DedicatedSystemMemory
);
361 ok_(__FILE__
, line
)(desc
->SharedSystemMemory
== expected_desc
->SharedSystemMemory
,
362 "Got shared system memory %Iu, expected %Iu.\n",
363 desc
->SharedSystemMemory
, expected_desc
->SharedSystemMemory
);
364 ok_(__FILE__
, line
)(equal_luid(desc
->AdapterLuid
, expected_desc
->AdapterLuid
),
365 "Got LUID %08lx:%08lx, expected %08lx:%08lx.\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(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
391 hr
= IDXGIOutput_GetDesc(output2
, &desc2
);
392 ok(hr
== S_OK
, "Got unexpected hr %#lx.\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(hr
== S_OK
, "Got unexpected hr %#lx.\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(hr
== S_OK
, "Got unexpected hr %#lx.\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 %#lx, expected %#lx.\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 %#lx, expected %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\n", hr
);
523 hr
= IDXGIOutput_GetParent(containing_output
, &IID_IDXGIAdapter
, (void **)&adapter
);
524 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get parent, hr %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\n", hr
);
687 hr
= IDXGIFactory_EnumAdapters(factory
, use_adapter_idx
, &adapter
);
689 IDXGIFactory_Release(factory
);
691 trace("Failed to get adapter, hr %#lx.\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
, "Got unexpected hr %#lx.\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 %#lx.\n", hr
);
828 hr
= ID3D12CommandQueue_Signal(queue
, fence
, 1);
829 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to signal fence, hr %#lx.\n", hr
);
830 hr
= wait_for_fence(fence
, 1);
831 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to wait for fence, hr %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\n", hr
);
873 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)factory
);
874 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get parent, hr %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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 %#lx.\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(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
962 hr
= IDXGIAdapter_GetDesc(adapter
, NULL
);
963 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
965 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
966 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
968 trace("%s.\n", wine_dbgstr_w(desc
.Description
));
969 trace("%04x: %04x:%04x (rev %02x).\n",
970 desc
.SubSysId
, desc
.VendorId
, desc
.DeviceId
, desc
.Revision
);
971 trace("Dedicated video memory: %Iu (%Iu MB).\n",
972 desc
.DedicatedVideoMemory
, desc
.DedicatedVideoMemory
/ (1024 * 1024));
973 trace("Dedicated system memory: %Iu (%Iu MB).\n",
974 desc
.DedicatedSystemMemory
, desc
.DedicatedSystemMemory
/ (1024 * 1024));
975 trace("Shared system memory: %Iu (%Iu MB).\n",
976 desc
.SharedSystemMemory
, desc
.SharedSystemMemory
/ (1024 * 1024));
977 trace("LUID: %08lx:%08lx.\n", desc
.AdapterLuid
.HighPart
, desc
.AdapterLuid
.LowPart
);
979 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
980 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#lx.\n", hr
);
981 if (hr
== E_NOINTERFACE
)
984 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &desc1
);
985 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
987 ok(!lstrcmpW(desc
.Description
, desc1
.Description
),
988 "Got unexpected description %s.\n", wine_dbgstr_w(desc1
.Description
));
989 ok(desc1
.VendorId
== desc
.VendorId
, "Got unexpected vendor ID %04x.\n", desc1
.VendorId
);
990 ok(desc1
.DeviceId
== desc
.DeviceId
, "Got unexpected device ID %04x.\n", desc1
.DeviceId
);
991 ok(desc1
.SubSysId
== desc
.SubSysId
, "Got unexpected sub system ID %04x.\n", desc1
.SubSysId
);
992 ok(desc1
.Revision
== desc
.Revision
, "Got unexpected revision %02x.\n", desc1
.Revision
);
993 ok(desc1
.DedicatedVideoMemory
== desc
.DedicatedVideoMemory
,
994 "Got unexpected dedicated video memory %Iu.\n", desc1
.DedicatedVideoMemory
);
995 ok(desc1
.DedicatedSystemMemory
== desc
.DedicatedSystemMemory
,
996 "Got unexpected dedicated system memory %Iu.\n", desc1
.DedicatedSystemMemory
);
997 ok(desc1
.SharedSystemMemory
== desc
.SharedSystemMemory
,
998 "Got unexpected shared system memory %Iu.\n", desc1
.SharedSystemMemory
);
999 ok(equal_luid(desc1
.AdapterLuid
, desc
.AdapterLuid
),
1000 "Got unexpected adapter LUID %08lx:%08lx.\n", desc1
.AdapterLuid
.HighPart
, desc1
.AdapterLuid
.LowPart
);
1001 trace("Flags: %08x.\n", desc1
.Flags
);
1003 IDXGIAdapter1_Release(adapter1
);
1006 IDXGIAdapter_Release(adapter
);
1007 refcount
= IDXGIDevice_Release(device
);
1008 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1011 static void test_adapter_luid(void)
1013 DXGI_ADAPTER_DESC device_adapter_desc
, desc
, desc2
;
1014 static const LUID luid
= {0xdeadbeef, 0xdeadbeef};
1015 IDXGIAdapter
*adapter
, *adapter2
;
1016 unsigned int found_adapter_count
;
1017 unsigned int adapter_index
;
1018 BOOL is_null_luid_adapter
;
1019 IDXGIFactory4
*factory4
;
1020 IDXGIFactory
*factory
;
1021 BOOL have_unique_luid
;
1022 IDXGIDevice
*device
;
1026 if (!(device
= create_device(0)))
1028 skip("Failed to create device.\n");
1032 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1033 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1034 hr
= IDXGIAdapter_GetDesc(adapter
, &device_adapter_desc
);
1035 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1036 IDXGIAdapter_Release(adapter
);
1037 refcount
= IDXGIDevice_Release(device
);
1038 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1040 is_null_luid_adapter
= !device_adapter_desc
.AdapterLuid
.LowPart
1041 && !device_adapter_desc
.SubSysId
&& !device_adapter_desc
.Revision
1042 && !device_adapter_desc
.VendorId
&& !device_adapter_desc
.DeviceId
;
1044 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
1045 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1047 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory4
, (void **)&factory4
);
1048 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
1050 have_unique_luid
= TRUE
;
1051 found_adapter_count
= 0;
1053 while ((hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)) == S_OK
)
1055 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1056 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1058 if (equal_luid(desc
.AdapterLuid
, device_adapter_desc
.AdapterLuid
))
1060 check_adapter_desc(&desc
, &device_adapter_desc
);
1061 ++found_adapter_count
;
1064 if (equal_luid(desc
.AdapterLuid
, luid
))
1065 have_unique_luid
= FALSE
;
1069 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, desc
.AdapterLuid
,
1070 &IID_IDXGIAdapter
, (void **)&adapter2
);
1071 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1072 hr
= IDXGIAdapter_GetDesc(adapter2
, &desc2
);
1073 ok(hr
== S_OK
, "Failed to get adapter desc, hr %#lx.\n", hr
);
1074 check_adapter_desc(&desc2
, &desc
);
1075 ok(adapter2
!= adapter
, "Expected to get new instance of IDXGIAdapter.\n");
1076 refcount
= IDXGIAdapter_Release(adapter2
);
1077 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
1080 refcount
= IDXGIAdapter_Release(adapter
);
1081 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
1085 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#lx.\n", hr
);
1087 /* Older versions of WARP aren't enumerated by IDXGIFactory_EnumAdapters(). */
1088 ok(found_adapter_count
== 1 || broken(is_null_luid_adapter
),
1089 "Found %u adapters for LUID %08lx:%08lx.\n",
1090 found_adapter_count
, device_adapter_desc
.AdapterLuid
.HighPart
,
1091 device_adapter_desc
.AdapterLuid
.LowPart
);
1094 IDXGIFactory4_Release(factory4
);
1095 refcount
= IDXGIFactory_Release(factory
);
1096 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
1098 if (!pCreateDXGIFactory2
1099 || FAILED(hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory4
, (void **)&factory4
)))
1101 skip("DXGI 1.4 is not available.\n");
1105 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1106 &IID_IDXGIAdapter
, NULL
);
1107 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1109 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, device_adapter_desc
.AdapterLuid
,
1110 &IID_IDXGIAdapter
, (void **)&adapter
);
1111 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1114 hr
= IDXGIAdapter_GetDesc(adapter
, &desc
);
1115 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1116 check_adapter_desc(&desc
, &device_adapter_desc
);
1117 refcount
= IDXGIAdapter_Release(adapter
);
1118 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
1121 if (have_unique_luid
)
1123 hr
= IDXGIFactory4_EnumAdapterByLuid(factory4
, luid
, &IID_IDXGIAdapter
, (void **)&adapter
);
1124 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#lx.\n", hr
);
1128 skip("Our LUID is not unique.\n");
1131 refcount
= IDXGIFactory4_Release(factory4
);
1132 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
1135 static void test_query_video_memory_info(void)
1137 DXGI_QUERY_VIDEO_MEMORY_INFO memory_info
;
1138 IDXGIAdapter3
*adapter3
;
1139 IDXGIAdapter
*adapter
;
1140 IDXGIDevice
*device
;
1144 if (!(device
= create_device(0)))
1146 skip("Failed to create device.\n");
1150 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1151 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1152 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter3
, (void **)&adapter3
);
1153 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
1154 if (hr
== E_NOINTERFACE
)
1157 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL
, &memory_info
);
1158 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1159 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1160 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1161 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1162 wine_dbgstr_longlong(memory_info
.Budget
));
1163 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1164 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1166 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
, &memory_info
);
1167 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1168 ok(memory_info
.Budget
>= memory_info
.AvailableForReservation
,
1169 "Available for reservation 0x%s is greater than budget 0x%s.\n",
1170 wine_dbgstr_longlong(memory_info
.AvailableForReservation
),
1171 wine_dbgstr_longlong(memory_info
.Budget
));
1172 ok(!memory_info
.CurrentReservation
, "Got unexpected current reservation 0x%s.\n",
1173 wine_dbgstr_longlong(memory_info
.CurrentReservation
));
1175 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
+ 1, &memory_info
);
1176 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1178 IDXGIAdapter3_Release(adapter3
);
1181 IDXGIAdapter_Release(adapter
);
1182 refcount
= IDXGIDevice_Release(device
);
1183 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1186 static void test_check_interface_support(void)
1188 LARGE_INTEGER driver_version
;
1189 IDXGIAdapter
*adapter
;
1190 IDXGIDevice
*device
;
1195 if (!(device
= create_device(0)))
1197 skip("Failed to create device.\n");
1201 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1202 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1204 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, NULL
);
1205 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1206 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_IDXGIDevice
, &driver_version
);
1207 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1208 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, NULL
);
1209 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1210 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device
, &driver_version
);
1211 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1213 trace("UMD version: %u.%u.%u.%u.\n",
1214 HIWORD(U(driver_version
).HighPart
), LOWORD(U(driver_version
).HighPart
),
1215 HIWORD(U(driver_version
).LowPart
), LOWORD(U(driver_version
).LowPart
));
1217 hr
= IDXGIDevice_QueryInterface(device
, &IID_ID3D10Device1
, (void **)&iface
);
1220 IUnknown_Release(iface
);
1221 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, NULL
);
1222 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1223 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D10Device1
, &driver_version
);
1224 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1228 win_skip("D3D10.1 is not supported.\n");
1231 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, NULL
);
1232 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#lx.\n", hr
);
1233 driver_version
.LowPart
= driver_version
.HighPart
= 0xdeadbeef;
1234 hr
= IDXGIAdapter_CheckInterfaceSupport(adapter
, &IID_ID3D11Device
, &driver_version
);
1235 ok(hr
== DXGI_ERROR_UNSUPPORTED
, "Got unexpected hr %#lx.\n", hr
);
1236 ok(driver_version
.HighPart
== 0xdeadbeef, "Got unexpected driver version %#lx.\n", driver_version
.HighPart
);
1237 ok(driver_version
.LowPart
== 0xdeadbeef, "Got unexpected driver version %#lx.\n", driver_version
.LowPart
);
1239 IDXGIAdapter_Release(adapter
);
1240 refcount
= IDXGIDevice_Release(device
);
1241 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1244 static void test_create_surface(void)
1246 ID3D11Texture2D
*texture2d
;
1247 DXGI_SURFACE_DESC desc
;
1248 IDXGISurface
*surface
;
1249 IDXGIDevice
*device
;
1253 if (!(device
= create_device(0)))
1255 skip("Failed to create device.\n");
1261 desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1262 desc
.SampleDesc
.Count
= 1;
1263 desc
.SampleDesc
.Quality
= 0;
1265 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1266 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1268 check_interface(surface
, &IID_ID3D10Texture2D
, TRUE
, FALSE
);
1269 /* Not available on all Windows versions. */
1270 check_interface(surface
, &IID_ID3D11Texture2D
, TRUE
, TRUE
);
1271 /* Not available on all Windows versions. */
1272 check_interface(surface
, &IID_IDXGISurface1
, TRUE
, TRUE
);
1274 IDXGISurface_Release(surface
);
1275 refcount
= IDXGIDevice_Release(device
);
1276 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1278 /* DXGI_USAGE_UNORDERED_ACCESS */
1279 if (!(device
= create_d3d11_device()))
1281 skip("Failed to create D3D11 device.\n");
1286 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_UNORDERED_ACCESS
, NULL
, &surface
);
1287 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1291 ID3D11UnorderedAccessView
*uav
;
1292 ID3D11Device
*d3d_device
;
1294 hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture2d
);
1295 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1297 ID3D11Texture2D_GetDevice(texture2d
, &d3d_device
);
1299 hr
= ID3D11Device_CreateUnorderedAccessView(d3d_device
, (ID3D11Resource
*)texture2d
, NULL
, &uav
);
1300 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1301 ID3D11UnorderedAccessView_Release(uav
);
1303 ID3D11Device_Release(d3d_device
);
1304 ID3D11Texture2D_Release(texture2d
);
1306 IDXGISurface_Release(surface
);
1309 refcount
= IDXGIDevice_Release(device
);
1310 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1313 static void test_parents(void)
1315 DXGI_SURFACE_DESC surface_desc
;
1316 IDXGISurface
*surface
;
1317 IDXGIFactory
*factory
;
1318 IDXGIAdapter
*adapter
;
1319 IDXGIDevice
*device
;
1320 IDXGIOutput
*output
;
1325 if (!(device
= create_device(0)))
1327 skip("Failed to create device.\n");
1331 surface_desc
.Width
= 512;
1332 surface_desc
.Height
= 512;
1333 surface_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1334 surface_desc
.SampleDesc
.Count
= 1;
1335 surface_desc
.SampleDesc
.Quality
= 0;
1337 hr
= IDXGIDevice_CreateSurface(device
, &surface_desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1338 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1340 hr
= IDXGISurface_GetParent(surface
, &IID_IDXGIDevice
, (void **)&parent
);
1341 IDXGISurface_Release(surface
);
1342 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1343 ok(parent
== (IUnknown
*)device
, "Got parent %p, expected %p.\n", parent
, device
);
1344 IUnknown_Release(parent
);
1346 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1347 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1349 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1350 if (hr
== DXGI_ERROR_NOT_FOUND
)
1352 skip("Adapter has not outputs.\n");
1356 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1358 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&parent
);
1359 IDXGIOutput_Release(output
);
1360 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1361 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1362 IUnknown_Release(parent
);
1365 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1366 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1368 hr
= IDXGIFactory_GetParent(factory
, &IID_IUnknown
, (void **)&parent
);
1369 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
1370 ok(parent
== NULL
, "Got parent %p, expected %p.\n", parent
, NULL
);
1371 IDXGIFactory_Release(factory
);
1373 hr
= IDXGIDevice_GetParent(device
, &IID_IDXGIAdapter
, (void **)&parent
);
1374 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1375 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1376 IUnknown_Release(parent
);
1378 IDXGIAdapter_Release(adapter
);
1379 refcount
= IDXGIDevice_Release(device
);
1380 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1383 static void test_output(void)
1385 unsigned int mode_count
, mode_count_comp
, i
, last_height
, last_width
;
1386 double last_refresh_rate
;
1387 IDXGIAdapter
*adapter
;
1388 IDXGIDevice
*device
;
1390 IDXGIOutput
*output
;
1392 DXGI_MODE_DESC
*modes
;
1394 if (!(device
= create_device(0)))
1396 skip("Failed to create device.\n");
1400 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1401 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1403 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, NULL
);
1404 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1406 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1407 if (hr
== DXGI_ERROR_NOT_FOUND
)
1409 skip("Adapter doesn't have any outputs.\n");
1410 IDXGIAdapter_Release(adapter
);
1411 IDXGIDevice_Release(device
);
1414 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1416 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, NULL
, NULL
);
1417 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1419 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1420 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Remote Desktop Services / Win 7 testbot */
1421 "Got unexpected hr %#lx.\n", hr
);
1422 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1424 win_skip("GetDisplayModeList() not supported.\n");
1425 IDXGIOutput_Release(output
);
1426 IDXGIAdapter_Release(adapter
);
1427 IDXGIDevice_Release(device
);
1430 mode_count_comp
= mode_count
;
1432 hr
= IDXGIOutput_GetDisplayModeList(output
, 0, 0, &mode_count
, NULL
);
1433 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1434 ok(!mode_count
, "Got unexpected mode_count %u.\n", mode_count
);
1436 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1437 DXGI_ENUM_MODES_SCALING
, &mode_count
, NULL
);
1438 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1439 ok(mode_count
>= mode_count_comp
, "Got unexpected mode_count %u, expected >= %u.\n", mode_count
, mode_count_comp
);
1440 mode_count_comp
= mode_count
;
1442 modes
= heap_calloc(mode_count
+ 10, sizeof(*modes
));
1443 ok(!!modes
, "Failed to allocate memory.\n");
1445 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1446 DXGI_ENUM_MODES_SCALING
, NULL
, modes
);
1447 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1448 ok(!modes
[0].Height
, "No output was expected.\n");
1451 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1452 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1453 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
1454 ok(!modes
[0].Height
, "No output was expected.\n");
1456 mode_count
= mode_count_comp
;
1457 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1458 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1459 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1460 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1462 last_width
= last_height
= 0;
1463 last_refresh_rate
= 0.;
1464 for (i
= 0; i
< mode_count
; i
++)
1466 double refresh_rate
= modes
[i
].RefreshRate
.Numerator
/ (double)modes
[i
].RefreshRate
.Denominator
;
1468 ok(modes
[i
].Width
&& modes
[i
].Height
, "Mode %u: Invalid dimensions %ux%u.\n",
1469 i
, modes
[i
].Width
, modes
[i
].Height
);
1471 ok(modes
[i
].Width
>= last_width
,
1472 "Mode %u: Modes should have been sorted, width %u < %u.\n", i
, modes
[i
].Width
, last_width
);
1473 if (modes
[i
].Width
!= last_width
)
1475 last_width
= modes
[i
].Width
;
1477 last_refresh_rate
= 0.;
1481 ok(modes
[i
].Height
>= last_height
,
1482 "Mode %u: Modes should have been sorted, height %u < %u.\n", i
, modes
[i
].Height
, last_height
);
1483 if (modes
[i
].Height
!= last_height
)
1485 last_height
= modes
[i
].Height
;
1486 last_refresh_rate
= 0.;
1490 ok(refresh_rate
>= last_refresh_rate
,
1491 "Mode %u: Modes should have been sorted, refresh rate %f < %f.\n", i
, refresh_rate
, last_refresh_rate
);
1492 if (refresh_rate
!= last_refresh_rate
)
1493 last_refresh_rate
= refresh_rate
;
1497 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1498 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1499 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1500 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1502 if (mode_count_comp
)
1504 mode_count
= mode_count_comp
- 1;
1505 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1506 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1507 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
1508 ok(mode_count
== mode_count_comp
- 1, "Got unexpected mode_count %u, expected %u.\n",
1509 mode_count
, mode_count_comp
- 1);
1513 skip("Not enough modes for test.\n");
1517 IDXGIOutput_Release(output
);
1518 IDXGIAdapter_Release(adapter
);
1519 refcount
= IDXGIDevice_Release(device
);
1520 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1523 static void test_find_closest_matching_mode(void)
1525 static const DXGI_MODE_SCALING scaling_tests
[] =
1527 DXGI_MODE_SCALING_CENTERED
,
1528 DXGI_MODE_SCALING_STRETCHED
1530 DXGI_MODE_DESC
*modes
, mode
, matching_mode
;
1531 unsigned int i
, j
, mode_count
;
1532 IDXGIAdapter
*adapter
;
1533 IDXGIDevice
*device
;
1534 IDXGIOutput
*output
;
1538 if (!(device
= create_device(0)))
1540 skip("Failed to create device.\n");
1544 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1545 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1547 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1548 if (hr
== DXGI_ERROR_NOT_FOUND
)
1550 win_skip("Adapter doesn't have any outputs.\n");
1551 IDXGIAdapter_Release(adapter
);
1552 IDXGIDevice_Release(device
);
1555 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1557 memset(&mode
, 0, sizeof(mode
));
1558 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1559 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
1560 "Got unexpected hr %#lx.\n", hr
);
1561 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1563 win_skip("FindClosestMatchingMode() not supported.\n");
1567 memset(&mode
, 0, sizeof(mode
));
1568 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, (IUnknown
*)device
);
1569 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1571 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1572 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1574 modes
= heap_calloc(mode_count
, sizeof(*modes
));
1575 ok(!!modes
, "Failed to allocate memory.\n");
1577 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
1578 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1580 for (i
= 0; i
< mode_count
; ++i
)
1583 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1584 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1585 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
);
1587 mode
.Format
= DXGI_FORMAT_UNKNOWN
;
1588 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1589 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1593 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1594 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1598 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1599 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1602 mode
.Width
= mode
.Height
= 0;
1603 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1604 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1605 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_RESOLUTION
);
1606 ok(matching_mode
.Width
> 0 && matching_mode
.Height
> 0, "Got unexpected resolution %ux%u.\n",
1607 matching_mode
.Width
, matching_mode
.Height
);
1610 mode
.RefreshRate
.Numerator
= mode
.RefreshRate
.Denominator
= 0;
1611 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1612 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1613 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_REFRESH_RATE
);
1614 ok(matching_mode
.RefreshRate
.Numerator
> 0 && matching_mode
.RefreshRate
.Denominator
> 0,
1615 "Got unexpected refresh rate %u / %u.\n",
1616 matching_mode
.RefreshRate
.Numerator
, matching_mode
.RefreshRate
.Denominator
);
1619 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1620 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1621 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1622 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1623 ok(matching_mode
.ScanlineOrdering
, "Got unexpected scanline ordering %#x.\n",
1624 matching_mode
.ScanlineOrdering
);
1626 memset(&mode
, 0, sizeof(mode
));
1627 mode
.Width
= modes
[i
].Width
;
1628 mode
.Height
= modes
[i
].Height
;
1629 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1630 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1631 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1632 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1634 memset(&mode
, 0, sizeof(mode
));
1635 mode
.Width
= modes
[i
].Width
- 1;
1636 mode
.Height
= modes
[i
].Height
- 1;
1637 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1638 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1639 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1640 check_mode_desc(&matching_mode
, &modes
[i
],
1641 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1643 memset(&mode
, 0, sizeof(mode
));
1644 mode
.Width
= modes
[i
].Width
+ 1;
1645 mode
.Height
= modes
[i
].Height
+ 1;
1646 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1647 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1648 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1649 check_mode_desc(&matching_mode
, &modes
[i
],
1650 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1653 memset(&mode
, 0, sizeof(mode
));
1654 mode
.Width
= mode
.Height
= 10;
1655 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1656 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1657 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1658 /* Find mode for the lowest resolution. */
1660 for (i
= 0; i
< mode_count
; ++i
)
1662 if (mode
.Width
>= modes
[i
].Width
&& mode
.Height
>= modes
[i
].Height
)
1665 check_mode_desc(&matching_mode
, &mode
, MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1667 memset(&mode
, 0, sizeof(mode
));
1668 mode
.Width
= modes
[0].Width
;
1669 mode
.Height
= modes
[0].Height
;
1670 mode
.Format
= modes
[0].Format
;
1671 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST
;
1672 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1673 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1674 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1676 memset(&mode
, 0, sizeof(mode
));
1677 mode
.Width
= modes
[0].Width
;
1678 mode
.Height
= modes
[0].Height
;
1679 mode
.Format
= modes
[0].Format
;
1680 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST
;
1681 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1682 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1683 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1685 for (i
= 0; i
< ARRAY_SIZE(scaling_tests
); ++i
)
1687 for (j
= 0; j
< mode_count
; ++j
)
1689 if (modes
[j
].Scaling
!= scaling_tests
[i
])
1692 memset(&mode
, 0, sizeof(mode
));
1693 mode
.Width
= modes
[j
].Width
;
1694 mode
.Height
= modes
[j
].Height
;
1695 mode
.Format
= modes
[j
].Format
;
1696 mode
.Scaling
= modes
[j
].Scaling
;
1697 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1698 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1699 check_mode_desc(&matching_mode
, &modes
[j
],
1700 MODE_DESC_IGNORE_REFRESH_RATE
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1708 IDXGIOutput_Release(output
);
1709 IDXGIAdapter_Release(adapter
);
1710 refcount
= IDXGIDevice_Release(device
);
1711 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1714 struct refresh_rates
1718 BOOL numerator_should_pass
;
1719 BOOL denominator_should_pass
;
1722 static void test_create_swapchain(void)
1724 struct swapchain_fullscreen_state initial_state
, expected_state
;
1725 unsigned int i
, expected_width
, expected_height
;
1726 DXGI_SWAP_CHAIN_DESC creation_desc
, result_desc
;
1727 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc
;
1728 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
1729 IDXGIDevice
*device
, *bgra_device
;
1730 ULONG refcount
, expected_refcount
;
1731 IUnknown
*obj
, *obj2
, *parent
;
1732 IDXGISwapChain1
*swapchain1
;
1733 RECT
*expected_client_rect
;
1734 IDXGISwapChain
*swapchain
;
1735 IDXGISurface1
*surface
;
1736 IDXGIAdapter
*adapter
;
1737 IDXGIFactory
*factory
;
1738 IDXGIOutput
*target
;
1743 const struct refresh_rates refresh_list
[] =
1745 {60, 60, FALSE
, FALSE
},
1746 {60, 0, TRUE
, FALSE
},
1747 {60, 1, TRUE
, TRUE
},
1748 { 0, 60, TRUE
, FALSE
},
1749 { 0, 0, TRUE
, FALSE
},
1752 if (!(device
= create_device(0)))
1754 skip("Failed to create device.\n");
1758 creation_desc
.BufferDesc
.Width
= 800;
1759 creation_desc
.BufferDesc
.Height
= 600;
1760 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
1761 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
1762 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1763 creation_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1764 creation_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
1765 creation_desc
.SampleDesc
.Count
= 1;
1766 creation_desc
.SampleDesc
.Quality
= 0;
1767 creation_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1768 creation_desc
.BufferCount
= 1;
1769 creation_desc
.OutputWindow
= NULL
;
1770 creation_desc
.Windowed
= TRUE
;
1771 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
1772 creation_desc
.Flags
= 0;
1774 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
1775 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1777 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1778 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1780 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1781 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1783 expected_refcount
= get_refcount(adapter
);
1784 refcount
= get_refcount(factory
);
1785 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1786 refcount
= get_refcount(device
);
1787 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1789 creation_desc
.OutputWindow
= NULL
;
1790 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1791 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1793 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1794 memset(&initial_state
, 0, sizeof(initial_state
));
1795 capture_fullscreen_state(&initial_state
.fullscreen_state
, creation_desc
.OutputWindow
);
1797 hr
= IDXGIFactory_CreateSwapChain(factory
, NULL
, &creation_desc
, &swapchain
);
1798 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1799 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, NULL
, &swapchain
);
1800 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1801 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, NULL
);
1802 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1803 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1804 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1806 refcount
= get_refcount(adapter
);
1807 ok(refcount
>= expected_refcount
, "Got refcount %lu, expected >= %lu.\n", refcount
, expected_refcount
);
1808 refcount
= get_refcount(factory
);
1809 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1810 refcount
= get_refcount(device
);
1811 ok(refcount
== 3, "Got unexpected refcount %lu.\n", refcount
);
1813 hr
= IDXGISwapChain_GetDesc(swapchain
, NULL
);
1814 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1816 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IUnknown
, (void **)&parent
);
1817 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1818 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1819 refcount
= IUnknown_Release(parent
);
1820 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1822 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IDXGIFactory
, (void **)&parent
);
1823 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1824 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1825 refcount
= IUnknown_Release(parent
);
1826 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1828 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain1
, (void **)&swapchain1
);
1829 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
1830 "Got unexpected hr %#lx.\n", hr
);
1833 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, NULL
);
1834 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1835 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, &swapchain_desc
);
1836 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1837 ok(!swapchain_desc
.Stereo
, "Got unexpected stereo %#x.\n", swapchain_desc
.Stereo
);
1838 ok(swapchain_desc
.Scaling
== DXGI_SCALING_STRETCH
,
1839 "Got unexpected scaling %#x.\n", swapchain_desc
.Scaling
);
1840 ok(swapchain_desc
.AlphaMode
== DXGI_ALPHA_MODE_IGNORE
,
1841 "Got unexpected alpha mode %#x.\n", swapchain_desc
.AlphaMode
);
1842 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, NULL
);
1843 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1844 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, &fullscreen_desc
);
1845 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1846 ok(fullscreen_desc
.Windowed
== creation_desc
.Windowed
,
1847 "Got unexpected windowed %#x.\n", fullscreen_desc
.Windowed
);
1848 hr
= IDXGISwapChain1_GetHwnd(swapchain1
, &window
);
1849 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1850 ok(window
== creation_desc
.OutputWindow
, "Got unexpected window %p.\n", window
);
1851 IDXGISwapChain1_Release(swapchain1
);
1854 refcount
= IDXGISwapChain_Release(swapchain
);
1855 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
1857 refcount
= get_refcount(factory
);
1858 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1860 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1862 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1863 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1865 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1866 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1868 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1869 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1871 ok(result_desc
.Windowed
== creation_desc
.Windowed
, "Test %u: Got unexpected windowed %#x.\n",
1872 i
, result_desc
.Windowed
);
1874 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1875 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1876 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1878 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1879 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1880 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1882 fullscreen
= 0xdeadbeef;
1883 target
= (void *)0xdeadbeef;
1884 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1885 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1886 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1887 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1889 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
1890 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1891 fullscreen
= 0xdeadbeef;
1892 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
1893 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1894 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1895 target
= (void *)0xdeadbeef;
1896 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
1897 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1898 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1900 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
1901 IDXGISwapChain_Release(swapchain
);
1904 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
1906 /* Test GDI-compatible swapchain */
1907 bgra_device
= create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT
);
1908 ok(!!bgra_device
, "Failed to create BGRA capable device.\n");
1910 hr
= IDXGIDevice_QueryInterface(bgra_device
, &IID_IUnknown
, (void **)&obj2
);
1911 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1913 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1914 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1916 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1921 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1922 ok(FAILED(hr
), "Got unexpected hr %#lx.\n", hr
);
1924 IDXGISurface1_Release(surface
);
1925 IDXGISwapChain_Release(swapchain
);
1927 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
1928 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE
;
1930 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1931 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1933 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1934 creation_desc
.Flags
= 0;
1936 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1937 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1939 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1940 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1941 IDXGISurface1_ReleaseDC(surface
, NULL
);
1943 IDXGISurface1_Release(surface
);
1944 IDXGISwapChain_Release(swapchain
);
1948 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1949 IDXGISwapChain_Release(swapchain
);
1951 IUnknown_Release(obj2
);
1952 IDXGIDevice_Release(bgra_device
);
1954 creation_desc
.Windowed
= FALSE
;
1956 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1958 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1959 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1961 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1962 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1964 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1965 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1967 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1968 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1969 if (result_desc
.Windowed
!= creation_desc
.Windowed
)
1970 trace("Test %u: Failed to change fullscreen state.\n", i
);
1972 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1973 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1974 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1976 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1977 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1978 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1982 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1983 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1984 ok(fullscreen
== !result_desc
.Windowed
, "Test %u: Got fullscreen %#x, expected %#x.\n",
1985 i
, fullscreen
, result_desc
.Windowed
);
1986 ok(result_desc
.Windowed
? !target
: !!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1987 if (!result_desc
.Windowed
)
1989 IDXGIOutput
*containing_output
;
1990 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
1991 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1992 ok(containing_output
== target
, "Test %u: Got unexpected containing output pointer %p.\n",
1993 i
, containing_output
);
1994 IDXGIOutput_Release(containing_output
);
1996 ok(output_belongs_to_adapter(target
, adapter
),
1997 "Test %u: Output %p doesn't belong to adapter %p.\n",
1998 i
, target
, adapter
);
1999 IDXGIOutput_Release(target
);
2001 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
2002 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2004 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2005 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2006 ok(fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2008 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2009 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2010 ok(!!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2011 IDXGIOutput_Release(target
);
2014 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2015 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2017 fullscreen
= 0xdeadbeef;
2018 target
= (void *)0xdeadbeef;
2019 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
2020 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2021 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2022 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2024 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2025 IDXGISwapChain_Release(swapchain
);
2028 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2030 /* Test swapchain creation with DXGI_FORMAT_UNKNOWN. */
2031 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_UNKNOWN
;
2032 creation_desc
.Windowed
= TRUE
;
2033 creation_desc
.Flags
= 0;
2034 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2035 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
2037 creation_desc
.Windowed
= FALSE
;
2038 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2039 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
2041 creation_desc
.BufferCount
= 2;
2042 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
2043 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2044 ok(hr
== E_INVALIDARG
|| hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
2045 creation_desc
.BufferCount
= 1;
2046 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
2048 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2050 /* Test swapchain creation with backbuffer width and height equal to 0. */
2051 expected_state
= initial_state
;
2052 expected_client_rect
= &expected_state
.fullscreen_state
.client_rect
;
2055 expected_width
= expected_client_rect
->right
;
2056 expected_height
= expected_client_rect
->bottom
;
2058 creation_desc
.BufferDesc
.Width
= 0;
2059 creation_desc
.BufferDesc
.Height
= 0;
2060 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2061 creation_desc
.Windowed
= TRUE
;
2062 creation_desc
.Flags
= 0;
2063 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2064 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2065 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2066 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2067 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2068 result_desc
.BufferDesc
.Width
, expected_width
);
2069 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2070 result_desc
.BufferDesc
.Height
, expected_height
);
2071 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2072 IDXGISwapChain_Release(swapchain
);
2074 DestroyWindow(creation_desc
.OutputWindow
);
2075 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2076 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
2077 0, 0, 222, 222, 0, 0, 0, 0);
2078 expected_state
.fullscreen_state
.style
= WS_CLIPSIBLINGS
| WS_CAPTION
2079 | WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
2080 SetRect(&expected_state
.fullscreen_state
.window_rect
, 0, 0, 222, 222);
2081 GetClientRect(creation_desc
.OutputWindow
, expected_client_rect
);
2082 expected_width
= expected_client_rect
->right
;
2083 expected_height
= expected_client_rect
->bottom
;
2085 creation_desc
.BufferDesc
.Width
= 0;
2086 creation_desc
.BufferDesc
.Height
= 0;
2087 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2088 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2089 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2090 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2091 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2092 result_desc
.BufferDesc
.Width
, expected_width
);
2093 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2094 result_desc
.BufferDesc
.Height
, expected_height
);
2095 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2096 IDXGISwapChain_Release(swapchain
);
2098 DestroyWindow(creation_desc
.OutputWindow
);
2099 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2100 WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
2101 1, 1, 0, 0, 0, 0, 0, 0);
2102 expected_state
.fullscreen_state
.style
= WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
2103 expected_state
.fullscreen_state
.exstyle
= 0;
2104 SetRect(&expected_state
.fullscreen_state
.window_rect
, 1, 1, 1, 1);
2105 SetRectEmpty(expected_client_rect
);
2106 expected_width
= expected_height
= 8;
2108 creation_desc
.BufferDesc
.Width
= 0;
2109 creation_desc
.BufferDesc
.Height
= 0;
2110 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2111 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2112 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2113 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2114 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2115 result_desc
.BufferDesc
.Width
, expected_width
);
2116 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2117 result_desc
.BufferDesc
.Height
, expected_height
);
2118 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2119 IDXGISwapChain_Release(swapchain
);
2121 DestroyWindow(creation_desc
.OutputWindow
);
2122 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
2123 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2126 creation_desc
.Windowed
= FALSE
;
2127 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2128 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Got unexpected hr %#lx.\n", hr
);
2129 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2130 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2131 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2132 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2133 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2134 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2135 "Got unexpected hr %#lx.\n", hr
);
2136 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2137 IDXGISwapChain_Release(swapchain
);
2138 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2140 win_skip("GetContainingOutput() not supported.\n");
2143 if (result_desc
.Windowed
)
2145 win_skip("Fullscreen not supported.\n");
2146 IDXGIOutput_Release(expected_state
.target
);
2150 creation_desc
.BufferDesc
.Width
= 0;
2151 creation_desc
.BufferDesc
.Height
= 0;
2152 creation_desc
.Windowed
= FALSE
;
2153 creation_desc
.Flags
= 0;
2154 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2155 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2156 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2157 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2159 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2160 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2161 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2162 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2163 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2164 result_desc
.BufferDesc
.Width
, expected_width
);
2165 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2166 result_desc
.BufferDesc
.Height
, expected_height
);
2167 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2168 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2169 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2170 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2171 IDXGISwapChain_Release(swapchain
);
2173 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
2174 creation_desc
.BufferDesc
.Width
= 0;
2175 creation_desc
.BufferDesc
.Height
= 0;
2176 creation_desc
.Windowed
= FALSE
;
2177 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2178 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2179 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2180 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2181 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2183 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2184 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2185 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2186 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2187 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2188 result_desc
.BufferDesc
.Width
, expected_width
);
2189 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2190 result_desc
.BufferDesc
.Height
, expected_height
);
2191 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2192 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2193 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2194 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2195 IDXGISwapChain_Release(swapchain
);
2197 IDXGIOutput_Release(expected_state
.target
);
2200 IUnknown_Release(obj
);
2201 refcount
= IDXGIDevice_Release(device
);
2202 ok(!refcount
, "Device has %lu references left.\n", refcount
);
2203 refcount
= IDXGIAdapter_Release(adapter
);
2204 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
2205 refcount
= IDXGIFactory_Release(factory
);
2206 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
2207 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2208 DestroyWindow(creation_desc
.OutputWindow
);
2211 static void test_get_containing_output(IUnknown
*device
, BOOL is_d3d12
)
2213 unsigned int adapter_idx
, output_idx
, output_count
;
2214 DXGI_OUTPUT_DESC output_desc
, output_desc2
;
2215 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2216 IDXGIOutput
*output
, *output2
;
2217 MONITORINFOEXW monitor_info
;
2218 IDXGISwapChain
*swapchain
;
2219 IDXGIFactory
*factory
;
2220 IDXGIAdapter
*adapter
;
2221 POINT points
[4 * 16];
2229 adapter
= get_adapter(device
, is_d3d12
);
2232 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
2237 while ((hr
= IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
)) != DXGI_ERROR_NOT_FOUND
)
2239 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2240 IDXGIOutput_Release(output
);
2243 IDXGIAdapter_Release(adapter
);
2245 swapchain_desc
.BufferDesc
.Width
= 100;
2246 swapchain_desc
.BufferDesc
.Height
= 100;
2247 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2248 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2249 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2250 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2251 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2252 swapchain_desc
.SampleDesc
.Count
= 1;
2253 swapchain_desc
.SampleDesc
.Quality
= 0;
2254 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2255 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2256 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2257 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 0, 0, 100, 100, 0, 0, 0, 0);
2258 swapchain_desc
.Windowed
= TRUE
;
2259 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2260 swapchain_desc
.Flags
= 0;
2262 get_factory(device
, is_d3d12
, &factory
);
2263 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2264 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2266 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, 0);
2267 ok(!!monitor
, "MonitorFromWindow failed.\n");
2269 monitor_info
.cbSize
= sizeof(monitor_info
);
2270 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2271 ok(ret
, "Failed to get monitor info.\n");
2273 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2274 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2275 "Got unexpected hr %#lx.\n", hr
);
2276 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2278 win_skip("GetContainingOutput() not supported.\n");
2282 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2283 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2285 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2286 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2287 ok(output
!= output2
, "Got unexpected output pointers %p, %p.\n", output
, output2
);
2288 check_output_equal(output
, output2
);
2290 refcount
= IDXGIOutput_Release(output
);
2291 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
2292 refcount
= IDXGIOutput_Release(output2
);
2293 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
2295 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2296 "Got unexpected device name %s, expected %s.\n",
2297 wine_dbgstr_w(output_desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
2298 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2299 "Got unexpected desktop coordinates %s, expected %s.\n",
2300 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2301 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2303 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2306 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2309 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2310 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
,
2313 /* Move the OutputWindow to the current output. */
2314 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2315 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2316 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2318 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2321 win_skip("Adapter %u output %u: GetContainingOutput failed, hr %#lx.\n",
2322 adapter_idx
, output_idx
, hr
);
2323 IDXGIOutput_Release(output
);
2327 check_output_equal(output
, output2
);
2329 refcount
= IDXGIOutput_Release(output2
);
2330 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
2331 adapter_idx
, output_idx
, refcount
);
2333 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
2334 for (i
= 0; i
< 4; ++i
)
2336 static const POINT offsets
[] =
2339 {-49, 0}, {-50, 0}, {-51, 0},
2340 { 0, -49}, { 0, -50}, { 0, -51},
2341 {-49, -49}, {-50, -49}, {-51, -49},
2342 {-49, -50}, {-50, -50}, {-51, -50},
2343 {-49, -51}, {-50, -51}, {-51, -51},
2345 unsigned int x
= 0, y
= 0;
2350 x
= output_desc
.DesktopCoordinates
.left
;
2351 y
= output_desc
.DesktopCoordinates
.top
;
2354 x
= output_desc
.DesktopCoordinates
.right
;
2355 y
= output_desc
.DesktopCoordinates
.top
;
2358 x
= output_desc
.DesktopCoordinates
.right
;
2359 y
= output_desc
.DesktopCoordinates
.bottom
;
2362 x
= output_desc
.DesktopCoordinates
.left
;
2363 y
= output_desc
.DesktopCoordinates
.bottom
;
2367 for (j
= 0; j
< ARRAY_SIZE(offsets
); ++j
)
2369 unsigned int idx
= ARRAY_SIZE(offsets
) * i
+ j
;
2370 assert(idx
< ARRAY_SIZE(points
));
2371 points
[idx
].x
= x
+ offsets
[j
].x
;
2372 points
[idx
].y
= y
+ offsets
[j
].y
;
2376 for (i
= 0; i
< ARRAY_SIZE(points
); ++i
)
2378 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, points
[i
].x
, points
[i
].y
,
2379 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2380 ok(ret
, "Adapter %u output %u point %u: Failed to set window position.\n",
2381 adapter_idx
, output_idx
, i
);
2383 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, MONITOR_DEFAULTTONEAREST
);
2384 ok(!!monitor
, "Adapter %u output %u point %u: Failed to get monitor from window.\n",
2385 adapter_idx
, output_idx
, i
);
2387 monitor_info
.cbSize
= sizeof(monitor_info
);
2388 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2389 ok(ret
, "Adapter %u output %u point %u: Failed to get monitor info.\n", adapter_idx
,
2392 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2393 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
),
2394 "Adapter %u output %u point %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, i
, hr
);
2397 ok(!!output2
, "Adapter %u output %u point %u: Got unexpected containing output %p.\n",
2398 adapter_idx
, output_idx
, i
, output2
);
2399 hr
= IDXGIOutput_GetDesc(output2
, &output_desc
);
2400 ok(hr
== S_OK
, "Adapter %u output %u point %u: Got unexpected hr %#lx.\n",
2401 adapter_idx
, output_idx
, i
, hr
);
2402 refcount
= IDXGIOutput_Release(output2
);
2403 ok(!refcount
, "Adapter %u output %u point %u: IDXGIOutput has %lu references left.\n",
2404 adapter_idx
, output_idx
, i
, refcount
);
2406 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2407 "Adapter %u output %u point %u: Got unexpected device name %s, expected %s.\n",
2408 adapter_idx
, output_idx
, i
, wine_dbgstr_w(output_desc
.DeviceName
),
2409 wine_dbgstr_w(monitor_info
.szDevice
));
2410 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2411 "Adapter %u output %u point %u: Expect desktop coordinates %s, got %s.\n",
2412 adapter_idx
, output_idx
, i
,
2413 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2414 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2416 IDXGIOutput_Release(output
);
2418 IDXGIAdapter_Release(adapter
);
2421 /* Test GetContainingOutput with a full screen swapchain. The containing output should stay
2422 * the same even if the device window is moved */
2423 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2426 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
2430 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2433 win_skip("GetContainingOutput failed, hr %#lx.\n", hr
);
2434 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2438 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2441 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2444 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2445 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2446 IDXGIOutput_Release(output
);
2448 /* Move the OutputWindow to the current output. */
2449 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2450 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2451 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2453 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2454 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n",
2455 adapter_idx
, output_idx
, hr
);
2456 ok(fullscreen
, "Adapter %u output %u: Expect swapchain full screen.\n", adapter_idx
,
2458 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2459 adapter_idx
, output_idx
, output2
, output
);
2460 IDXGIOutput_Release(output
);
2462 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2463 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2464 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2465 adapter_idx
, output_idx
, output2
, output
);
2466 IDXGIOutput_Release(output
);
2468 IDXGIAdapter_Release(adapter
);
2471 IDXGIOutput_Release(output2
);
2472 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2473 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2475 /* Test GetContainingOutput after a full screen swapchain is made windowed by pressing
2476 * Alt+Enter, then move it to another output and use Alt+Enter to enter full screen */
2479 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2482 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
,
2483 output
? &output2
: &output
)); ++output_idx
)
2489 IDXGIAdapter_Release(adapter
);
2494 if (output
&& output2
)
2496 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2497 IDXGIOutput_Release(output
);
2500 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
2501 IDXGIOutput_Release(output2
);
2505 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to leave full screen on the first output */
2506 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2507 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2509 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2510 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2511 ok(!fullscreen
, "Expect swapchain not full screen.\n");
2513 /* Move the swapchain output window to the second output */
2514 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2515 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2516 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc2
.DesktopCoordinates
.left
,
2517 output_desc2
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2518 ok(ret
, "SetWindowPos failed.\n");
2520 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to enter full screen on the second output */
2521 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2522 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2525 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2526 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2527 ok(fullscreen
, "Expect swapchain full screen.\n");
2528 ok(!!output
, "Expect output not NULL.\n");
2529 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2530 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2531 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2532 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2533 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2534 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2535 wine_dbgstr_w(output_desc
.DeviceName
));
2536 IDXGIOutput_Release(output
);
2539 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2540 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2541 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2542 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2543 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2544 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2545 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2546 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2547 wine_dbgstr_w(output_desc
.DeviceName
));
2549 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2550 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2554 skip("This test requires two outputs.\n");
2558 IDXGIOutput_Release(output
);
2560 IDXGIOutput_Release(output2
);
2563 refcount
= IDXGISwapChain_Release(swapchain
);
2564 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2565 refcount
= IDXGIFactory_Release(factory
);
2566 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
2567 DestroyWindow(swapchain_desc
.OutputWindow
);
2570 static void test_swapchain_fullscreen_state(IDXGISwapChain
*swapchain
,
2571 IDXGIAdapter
*adapter
, const struct swapchain_fullscreen_state
*initial_state
)
2573 MONITORINFOEXW monitor_info
, *output_monitor_info
;
2574 struct swapchain_fullscreen_state expected_state
;
2575 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2576 DXGI_OUTPUT_DESC output_desc
;
2577 unsigned int i
, output_count
;
2578 IDXGIOutput
*output
;
2582 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
2583 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2585 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2587 expected_state
= *initial_state
;
2588 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2589 &swapchain_desc
, &initial_state
->fullscreen_state
.monitor_rect
, 800, 600, NULL
);
2590 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2591 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2593 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2594 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2597 skip("Could not change fullscreen state.\n");
2598 IDXGIOutput_Release(expected_state
.target
);
2601 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2603 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2604 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2605 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2607 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2608 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2609 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2611 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2612 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2613 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2615 IDXGIOutput_Release(expected_state
.target
);
2616 expected_state
.target
= NULL
;
2619 while (IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
) != DXGI_ERROR_NOT_FOUND
)
2621 IDXGIOutput_Release(output
);
2625 output_monitor_info
= heap_calloc(output_count
, sizeof(*output_monitor_info
));
2626 ok(!!output_monitor_info
, "Failed to allocate memory.\n");
2627 for (i
= 0; i
< output_count
; ++i
)
2629 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2630 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2632 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2633 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2635 output_monitor_info
[i
].cbSize
= sizeof(*output_monitor_info
);
2636 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&output_monitor_info
[i
]);
2637 ok(ret
, "Failed to get monitor info.\n");
2639 IDXGIOutput_Release(output
);
2642 for (i
= 0; i
< output_count
; ++i
)
2644 RECT orig_monitor_rect
= output_monitor_info
[i
].rcMonitor
;
2645 IDXGIOutput
*target
;
2648 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2649 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2650 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2651 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2653 expected_state
= *initial_state
;
2654 expected_state
.target
= output
;
2655 expected_state
.fullscreen_state
.monitor
= output_desc
.Monitor
;
2656 expected_state
.fullscreen_state
.monitor_rect
= orig_monitor_rect
;
2657 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2658 &swapchain_desc
, &orig_monitor_rect
, 800, 600, NULL
);
2660 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2661 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2662 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2665 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2666 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2667 ok(target
== output
, "Got target pointer %p, expected %p.\n", target
, output
);
2668 IDXGIOutput_Release(target
);
2670 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2671 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2672 ok(fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2674 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2675 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2676 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2677 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, output
);
2678 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
2679 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2680 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2681 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2682 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2685 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2686 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2687 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2689 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2690 monitor_info
.cbSize
= sizeof(monitor_info
);
2691 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2692 ok(ret
, "Failed to get monitor info.\n");
2693 ok(EqualRect(&monitor_info
.rcMonitor
, &orig_monitor_rect
), "Got monitor rect %s, expected %s.\n",
2694 wine_dbgstr_rect(&monitor_info
.rcMonitor
), wine_dbgstr_rect(&orig_monitor_rect
));
2696 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2697 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2699 IDXGIOutput_Release(output
);
2702 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2703 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2704 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2706 for (i
= 0; i
< output_count
; ++i
)
2708 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2709 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2711 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2712 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2714 monitor_info
.cbSize
= sizeof(monitor_info
);
2715 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2716 ok(ret
, "Failed to get monitor info.\n");
2718 ok(EqualRect(&monitor_info
.rcMonitor
, &output_monitor_info
[i
].rcMonitor
),
2719 "Got monitor rect %s, expected %s.\n",
2720 wine_dbgstr_rect(&monitor_info
.rcMonitor
),
2721 wine_dbgstr_rect(&output_monitor_info
[i
].rcMonitor
));
2723 IDXGIOutput_Release(output
);
2726 heap_free(output_monitor_info
);
2729 static void test_set_fullscreen(IUnknown
*device
, BOOL is_d3d12
)
2731 struct swapchain_fullscreen_state initial_state
;
2732 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2733 IDXGIAdapter
*adapter
= NULL
;
2734 IDXGISwapChain
*swapchain
;
2735 IDXGIFactory
*factory
;
2736 IDXGIOutput
*output
;
2741 get_factory(device
, is_d3d12
, &factory
);
2743 swapchain_desc
.BufferDesc
.Width
= 800;
2744 swapchain_desc
.BufferDesc
.Height
= 600;
2745 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2746 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2747 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2748 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2749 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2750 swapchain_desc
.SampleDesc
.Count
= 1;
2751 swapchain_desc
.SampleDesc
.Quality
= 0;
2752 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2753 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2754 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2755 swapchain_desc
.Windowed
= TRUE
;
2756 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2757 swapchain_desc
.Flags
= 0;
2759 memset(&initial_state
, 0, sizeof(initial_state
));
2760 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
2761 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2762 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2763 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2764 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2765 "Got unexpected hr %#lx.\n", hr
);
2768 skip("Could not get output.\n");
2771 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&adapter
);
2772 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2773 IDXGIOutput_Release(output
);
2775 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2776 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2777 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
2778 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2779 "Got unexpected hr %#lx.\n", hr
);
2782 skip("Could not change fullscreen state.\n");
2785 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2786 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2787 refcount
= IDXGISwapChain_Release(swapchain
);
2788 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2790 DestroyWindow(swapchain_desc
.OutputWindow
);
2791 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2792 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2793 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2794 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2795 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2796 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2797 refcount
= IDXGISwapChain_Release(swapchain
);
2798 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2800 DestroyWindow(swapchain_desc
.OutputWindow
);
2801 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2802 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2803 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2804 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2805 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2806 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2807 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2808 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2809 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2810 DestroyWindow(swapchain_desc
.OutputWindow
);
2811 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2812 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2813 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2814 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2815 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2816 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2817 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2818 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2819 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2820 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2821 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2822 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2823 refcount
= IDXGISwapChain_Release(swapchain
);
2824 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2826 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2827 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2828 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2829 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2830 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2831 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2832 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2833 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2834 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2835 DestroyWindow(swapchain_desc
.OutputWindow
);
2836 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2837 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2838 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2839 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2840 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2841 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2842 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2843 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2844 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2845 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2846 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2847 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2848 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2849 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2850 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2851 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2852 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2853 refcount
= IDXGISwapChain_Release(swapchain
);
2854 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2856 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2857 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2858 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2859 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2860 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2861 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2862 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2866 IDXGIAdapter_Release(adapter
);
2867 refcount
= IDXGISwapChain_Release(swapchain
);
2868 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2869 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2870 DestroyWindow(swapchain_desc
.OutputWindow
);
2872 refcount
= IDXGIFactory_Release(factory
);
2873 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
2876 static void test_default_fullscreen_target_output(IUnknown
*device
, BOOL is_d3d12
)
2878 IDXGIOutput
*output
, *containing_output
, *target
;
2879 unsigned int adapter_idx
, output_idx
;
2880 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2881 DXGI_OUTPUT_DESC output_desc
;
2882 unsigned int width
, height
;
2883 IDXGISwapChain
*swapchain
;
2884 IDXGIFactory
*factory
;
2885 IDXGIAdapter
*adapter
;
2886 BOOL fullscreen
, ret
;
2891 get_factory(device
, is_d3d12
, &factory
);
2893 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2894 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2895 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2896 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2897 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2898 swapchain_desc
.SampleDesc
.Count
= 1;
2899 swapchain_desc
.SampleDesc
.Quality
= 0;
2900 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2901 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2902 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2903 swapchain_desc
.Flags
= 0;
2905 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2908 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2911 /* Windowed swapchain */
2912 swapchain_desc
.BufferDesc
.Width
= 640;
2913 swapchain_desc
.BufferDesc
.Height
= 480;
2914 swapchain_desc
.OutputWindow
= create_window();
2915 swapchain_desc
.Windowed
= TRUE
;
2916 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2917 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2919 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
2920 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2921 ok(!fullscreen
, "Adapter %u output %u: Expected not fullscreen.\n", adapter_idx
, output_idx
);
2922 ok(!containing_output
, "Adapter %u output %u: Expected a null output.\n", adapter_idx
, output_idx
);
2924 /* Move the OutputWindow to the current output. */
2925 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2926 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2927 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0,
2928 output_desc
.DesktopCoordinates
.left
, output_desc
.DesktopCoordinates
.top
,
2929 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2930 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#lx.\n", adapter_idx
,
2931 output_idx
, GetLastError());
2933 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2934 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2935 "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2936 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2938 win_skip("Adapter %u output %u: GetContainingOutput() not supported.\n",
2939 adapter_idx
, output_idx
);
2940 IDXGISwapChain_Release(swapchain
);
2941 IDXGIOutput_Release(output
);
2942 DestroyWindow(swapchain_desc
.OutputWindow
);
2946 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2947 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
2948 "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2949 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
2951 skip("Adapter %u output %u: Could not change fullscreen state.\n", adapter_idx
,
2953 IDXGIOutput_Release(containing_output
);
2954 IDXGISwapChain_Release(swapchain
);
2955 IDXGIOutput_Release(output
);
2956 DestroyWindow(swapchain_desc
.OutputWindow
);
2959 GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
2960 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
2961 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
2962 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2963 wine_dbgstr_rect(&window_rect
));
2966 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2967 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2968 ok(target
!= containing_output
,
2969 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
2970 output_idx
, target
, containing_output
);
2971 check_output_equal(target
, containing_output
);
2973 refcount
= IDXGIOutput_Release(containing_output
);
2974 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
2975 adapter_idx
, output_idx
, refcount
);
2977 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2978 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2979 ok(containing_output
== target
,
2980 "Adapter %u output %u: Got unexpected containing output %p, expected %p.\n",
2981 adapter_idx
, output_idx
, containing_output
, target
);
2982 refcount
= IDXGIOutput_Release(containing_output
);
2983 ok(refcount
>= 2, "Adapter %u output %u: Got unexpected refcount %lu.\n", adapter_idx
,
2984 output_idx
, refcount
);
2985 refcount
= IDXGIOutput_Release(target
);
2986 ok(refcount
>= 1, "Adapter %u output %u: Got unexpected refcount %lu.\n", adapter_idx
,
2987 output_idx
, refcount
);
2989 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2990 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2991 refcount
= IDXGISwapChain_Release(swapchain
);
2992 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %lu references left.\n",
2993 adapter_idx
, output_idx
, refcount
);
2994 DestroyWindow(swapchain_desc
.OutputWindow
);
2996 /* Full screen swapchain */
2997 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
2998 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
2999 swapchain_desc
.BufferDesc
.Width
= width
;
3000 swapchain_desc
.BufferDesc
.Height
= height
;
3001 swapchain_desc
.OutputWindow
= create_window();
3002 swapchain_desc
.Windowed
= FALSE
;
3003 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
3004 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
3005 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#lx.\n", adapter_idx
,
3006 output_idx
, GetLastError());
3007 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3010 skip("Adapter %u output %u: CreateSwapChain failed, hr %#lx.\n", adapter_idx
,
3012 IDXGIOutput_Release(output
);
3013 DestroyWindow(swapchain_desc
.OutputWindow
);
3017 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
3018 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3019 ok(fullscreen
, "Adapter %u output %u: Expected fullscreen.\n", adapter_idx
, output_idx
);
3020 ok(!!containing_output
, "Adapter %u output %u: Expected a valid output.\n", adapter_idx
, output_idx
);
3021 if (containing_output
)
3022 IDXGIOutput_Release(containing_output
);
3024 ret
= GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
3025 ok(ret
, "Adapter %u output %u: GetWindowRect failed, error %#lx.\n", adapter_idx
,
3026 output_idx
, GetLastError());
3027 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
3028 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
3029 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3030 wine_dbgstr_rect(&window_rect
));
3032 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
3033 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3034 ok(containing_output
!= output
,
3035 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
3036 output_idx
, output
, containing_output
);
3037 check_output_equal(output
, containing_output
);
3038 IDXGIOutput_Release(containing_output
);
3040 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3041 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3042 refcount
= IDXGISwapChain_Release(swapchain
);
3043 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %lu references left.\n",
3044 adapter_idx
, output_idx
, refcount
);
3045 refcount
= IDXGIOutput_Release(output
);
3046 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
3047 adapter_idx
, output_idx
, refcount
);
3048 DestroyWindow(swapchain_desc
.OutputWindow
);
3050 IDXGIAdapter_Release(adapter
);
3053 refcount
= IDXGIFactory_Release(factory
);
3054 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
3057 static void test_windowed_resize_target(IDXGISwapChain
*swapchain
, HWND window
,
3058 struct swapchain_fullscreen_state
*state
)
3060 struct swapchain_fullscreen_state expected_state
;
3061 struct fullscreen_state
*e
;
3062 DXGI_MODE_DESC mode
;
3070 unsigned int width
, height
;
3083 check_swapchain_fullscreen_state(swapchain
, state
);
3084 expected_state
= *state
;
3085 e
= &expected_state
.fullscreen_state
;
3087 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3089 SetRect(&e
->client_rect
, 0, 0, sizes
[i
].width
, sizes
[i
].height
);
3090 e
->window_rect
= e
->client_rect
;
3091 ret
= AdjustWindowRectEx(&e
->window_rect
, GetWindowLongW(window
, GWL_STYLE
),
3092 FALSE
, GetWindowLongW(window
, GWL_EXSTYLE
));
3093 ok(ret
, "AdjustWindowRectEx failed.\n");
3094 if (GetMenu(window
))
3095 e
->client_rect
.bottom
-= GetSystemMetrics(SM_CYMENU
);
3096 SetRect(&e
->window_rect
, 0, 0,
3097 e
->window_rect
.right
- e
->window_rect
.left
,
3098 e
->window_rect
.bottom
- e
->window_rect
.top
);
3099 GetWindowRect(window
, &window_rect
);
3100 OffsetRect(&e
->window_rect
, window_rect
.left
, window_rect
.top
);
3101 if (e
->window_rect
.right
>= e
->monitor_rect
.right
3102 || e
->window_rect
.bottom
>= e
->monitor_rect
.bottom
)
3104 skip("Test %u: Window %s does not fit on screen %s.\n",
3105 i
, wine_dbgstr_rect(&e
->window_rect
), wine_dbgstr_rect(&e
->monitor_rect
));
3109 memset(&mode
, 0, sizeof(mode
));
3110 mode
.Width
= sizes
[i
].width
;
3111 mode
.Height
= sizes
[i
].height
;
3112 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3113 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3114 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3117 ret
= SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOZORDER
);
3118 ok(ret
, "SetWindowPos failed, error %#lx.\n", GetLastError());
3119 GetWindowRect(window
, &e
->window_rect
);
3120 GetClientRect(window
, &e
->client_rect
);
3121 ret
= SetWindowPos(window
, 0, 0, 0, 200, 200, SWP_NOMOVE
| SWP_NOZORDER
);
3122 ok(ret
, "SetWindowPos failed, error %#lx.\n", GetLastError());
3124 memset(&mode
, 0, sizeof(mode
));
3125 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3126 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3127 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3129 GetWindowRect(window
, &e
->window_rect
);
3130 GetClientRect(window
, &e
->client_rect
);
3131 *state
= expected_state
;
3134 static void test_fullscreen_resize_target(IDXGISwapChain
*swapchain
,
3135 const struct swapchain_fullscreen_state
*initial_state
)
3137 struct swapchain_fullscreen_state expected_state
;
3138 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3139 DXGI_OUTPUT_DESC output_desc
;
3140 unsigned int i
, mode_count
;
3141 DXGI_MODE_DESC
*modes
;
3142 IDXGIOutput
*target
;
3145 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3146 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3148 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
3149 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3151 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
3152 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
3153 "Got unexpected hr %#lx.\n", hr
);
3154 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3156 win_skip("GetDisplayModeList() not supported.\n");
3157 IDXGIOutput_Release(target
);
3161 modes
= heap_calloc(mode_count
, sizeof(*modes
));
3162 ok(!!modes
, "Failed to allocate memory.\n");
3164 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
3165 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3167 expected_state
= *initial_state
;
3168 for (i
= 0; i
< min(mode_count
, 20); ++i
)
3170 /* FIXME: Modes with scaling aren't fully tested. */
3171 if (!(swapchain_desc
.Flags
& DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
)
3172 && modes
[i
].Scaling
!= DXGI_MODE_SCALING_UNSPECIFIED
)
3175 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3176 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3178 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3179 &swapchain_desc
, &output_desc
.DesktopCoordinates
, modes
[i
].Width
, modes
[i
].Height
, NULL
);
3181 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &modes
[i
]);
3182 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
3183 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3185 skip("Failed to change to video mode %u.\n", i
);
3188 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3190 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3191 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3192 ok(EqualRect(&output_desc
.DesktopCoordinates
, &expected_state
.fullscreen_state
.monitor_rect
),
3193 "Got desktop coordinates %s, expected %s.\n",
3194 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3195 wine_dbgstr_rect(&expected_state
.fullscreen_state
.monitor_rect
));
3199 IDXGIOutput_Release(target
);
3202 static void test_resize_target(IUnknown
*device
, BOOL is_d3d12
)
3204 struct swapchain_fullscreen_state initial_state
, expected_state
;
3205 unsigned int adapter_idx
, output_idx
, test_idx
;
3206 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3207 DXGI_OUTPUT_DESC output_desc
;
3208 IDXGISwapChain
*swapchain
;
3209 IDXGIFactory
*factory
;
3210 IDXGIAdapter
*adapter
;
3211 IDXGIOutput
*output
;
3224 {{ 0, 0}, TRUE
, FALSE
, 0},
3225 {{10, 10}, TRUE
, FALSE
, 0},
3226 {{ 0, 0}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3227 {{10, 10}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3228 {{ 0, 0}, FALSE
, FALSE
, 0},
3229 {{ 0, 0}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3230 {{10, 10}, FALSE
, FALSE
, 0},
3231 {{10, 10}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3232 {{ 0, 0}, FALSE
, TRUE
, 0},
3233 {{ 0, 0}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3234 {{10, 10}, FALSE
, TRUE
, 0},
3235 {{10, 10}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3238 get_factory(device
, is_d3d12
, &factory
);
3240 swapchain_desc
.BufferDesc
.Width
= 800;
3241 swapchain_desc
.BufferDesc
.Height
= 600;
3242 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3243 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3244 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3245 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3246 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3247 swapchain_desc
.SampleDesc
.Count
= 1;
3248 swapchain_desc
.SampleDesc
.Quality
= 0;
3249 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3250 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
3251 swapchain_desc
.Windowed
= TRUE
;
3252 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
3253 swapchain_desc
.Flags
= 0;
3255 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
3258 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
3261 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
3262 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3264 for (test_idx
= 0; test_idx
< ARRAY_SIZE(tests
); ++test_idx
)
3266 swapchain_desc
.Flags
= tests
[test_idx
].flags
;
3267 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0,
3268 output_desc
.DesktopCoordinates
.left
+ tests
[test_idx
].origin
.x
,
3269 output_desc
.DesktopCoordinates
.top
+ tests
[test_idx
].origin
.y
,
3270 400, 200, 0, 0, 0, 0);
3271 if (tests
[test_idx
].menu
)
3273 HMENU menu_bar
= CreateMenu();
3274 HMENU menu
= CreateMenu();
3275 AppendMenuA(menu_bar
, MF_POPUP
, (UINT_PTR
)menu
, "Menu");
3276 SetMenu(swapchain_desc
.OutputWindow
, menu_bar
);
3279 memset(&initial_state
, 0, sizeof(initial_state
));
3280 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3282 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3283 ok(hr
== S_OK
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3284 adapter_idx
, output_idx
, test_idx
, hr
);
3285 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3287 expected_state
= initial_state
;
3288 if (tests
[test_idx
].fullscreen
)
3290 expected_state
.fullscreen
= TRUE
;
3291 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3292 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 800, 600, NULL
);
3293 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
3294 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3295 "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3296 adapter_idx
, output_idx
, test_idx
, hr
);
3297 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3299 win_skip("Adapter %u output %u test %u: GetContainingOutput() not supported.\n",
3300 adapter_idx
, output_idx
, test_idx
);
3301 IDXGISwapChain_Release(swapchain
);
3302 DestroyWindow(swapchain_desc
.OutputWindow
);
3306 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
3307 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
3308 "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3309 adapter_idx
, output_idx
, test_idx
, hr
);
3310 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3312 skip("Adapter %u output %u test %u: Could not change fullscreen state.\n",
3313 adapter_idx
, output_idx
, test_idx
);
3314 IDXGIOutput_Release(expected_state
.target
);
3315 IDXGISwapChain_Release(swapchain
);
3316 DestroyWindow(swapchain_desc
.OutputWindow
);
3320 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3322 hr
= IDXGISwapChain_ResizeTarget(swapchain
, NULL
);
3323 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3324 adapter_idx
, output_idx
, test_idx
, hr
);
3325 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3327 if (tests
[test_idx
].fullscreen
)
3329 test_fullscreen_resize_target(swapchain
, &expected_state
);
3331 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3332 ok(hr
== S_OK
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3333 adapter_idx
, output_idx
, test_idx
, hr
);
3334 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3335 IDXGIOutput_Release(expected_state
.target
);
3336 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3337 expected_state
= initial_state
;
3341 test_windowed_resize_target(swapchain
, swapchain_desc
.OutputWindow
, &expected_state
);
3343 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3346 refcount
= IDXGISwapChain_Release(swapchain
);
3347 ok(!refcount
, "Adapter %u output %u test %u: IDXGISwapChain has %lu references left.\n",
3348 adapter_idx
, output_idx
, test_idx
, refcount
);
3349 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &expected_state
.fullscreen_state
);
3350 DestroyWindow(swapchain_desc
.OutputWindow
);
3352 IDXGIOutput_Release(output
);
3354 IDXGIAdapter_Release(adapter
);
3356 refcount
= IDXGIFactory_Release(factory
);
3357 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
3360 static LRESULT CALLBACK
resize_target_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
3362 IDXGISwapChain
*swapchain
= (IDXGISwapChain
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
3363 DXGI_SWAP_CHAIN_DESC desc
;
3369 ok(!!swapchain
, "GWLP_USERDATA is NULL.\n");
3370 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
3371 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3372 ok(desc
.BufferDesc
.Width
== 800, "Got unexpected buffer width %u.\n", desc
.BufferDesc
.Width
);
3373 ok(desc
.BufferDesc
.Height
== 600, "Got unexpected buffer height %u.\n", desc
.BufferDesc
.Height
);
3377 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
3381 struct window_thread_data
3384 HANDLE window_created
;
3388 static DWORD WINAPI
window_thread(void *data
)
3390 struct window_thread_data
*thread_data
= data
;
3395 memset(&wc
, 0, sizeof(wc
));
3396 wc
.lpfnWndProc
= resize_target_wndproc
;
3397 wc
.lpszClassName
= "dxgi_resize_target_wndproc_wc";
3398 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
3400 thread_data
->window
= CreateWindowA("dxgi_resize_target_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3401 ok(!!thread_data
->window
, "Failed to create window.\n");
3403 ret
= SetEvent(thread_data
->window_created
);
3404 ok(ret
, "Failed to set event, last error %#lx.\n", GetLastError());
3408 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3409 DispatchMessageA(&msg
);
3411 ret
= WaitForSingleObject(thread_data
->finished
, 0);
3412 if (ret
!= WAIT_TIMEOUT
)
3415 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for event, ret %#x, last error %#lx.\n", ret
, GetLastError());
3417 DestroyWindow(thread_data
->window
);
3418 thread_data
->window
= NULL
;
3420 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
3425 static void test_resize_target_wndproc(void)
3427 struct window_thread_data thread_data
;
3428 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3429 IDXGISwapChain
*swapchain
;
3430 IDXGIFactory
*factory
;
3431 IDXGIAdapter
*adapter
;
3432 DXGI_MODE_DESC mode
;
3433 IDXGIDevice
*device
;
3441 if (!(device
= create_device(0)))
3443 skip("Failed to create device.\n");
3447 memset(&thread_data
, 0, sizeof(thread_data
));
3448 thread_data
.window_created
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3449 ok(!!thread_data
.window_created
, "Failed to create event, last error %#lx.\n", GetLastError());
3450 thread_data
.finished
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3451 ok(!!thread_data
.finished
, "Failed to create event, last error %#lx.\n", GetLastError());
3453 thread
= CreateThread(NULL
, 0, window_thread
, &thread_data
, 0, NULL
);
3454 ok(!!thread
, "Failed to create thread, last error %#lx.\n", GetLastError());
3455 ret
= WaitForSingleObject(thread_data
.window_created
, INFINITE
);
3456 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#lx.\n", ret
, GetLastError());
3458 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3459 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3460 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3461 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3463 swapchain_desc
.BufferDesc
.Width
= 800;
3464 swapchain_desc
.BufferDesc
.Height
= 600;
3465 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3466 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3467 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3468 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3469 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3470 swapchain_desc
.SampleDesc
.Count
= 1;
3471 swapchain_desc
.SampleDesc
.Quality
= 0;
3472 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3473 swapchain_desc
.BufferCount
= 1;
3474 swapchain_desc
.OutputWindow
= thread_data
.window
;
3475 swapchain_desc
.Windowed
= TRUE
;
3476 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3477 swapchain_desc
.Flags
= 0;
3478 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3479 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3481 data
= SetWindowLongPtrA(thread_data
.window
, GWLP_USERDATA
, (LONG_PTR
)swapchain
);
3482 ok(!data
, "Got unexpected GWLP_USERDATA %p.\n", (void *)data
);
3484 memset(&mode
, 0, sizeof(mode
));
3487 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3488 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3490 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3491 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3492 ok(swapchain_desc
.BufferDesc
.Width
== 800,
3493 "Got unexpected buffer width %u.\n", swapchain_desc
.BufferDesc
.Width
);
3494 ok(swapchain_desc
.BufferDesc
.Height
== 600,
3495 "Got unexpected buffer height %u.\n", swapchain_desc
.BufferDesc
.Height
);
3497 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
3498 ok(ret
, "Failed to get client rect.\n");
3499 ok(rect
.right
== mode
.Width
&& rect
.bottom
== mode
.Height
,
3500 "Got unexpected client rect %s.\n", wine_dbgstr_rect(&rect
));
3502 refcount
= IDXGISwapChain_Release(swapchain
);
3503 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3505 IDXGIAdapter_Release(adapter
);
3506 refcount
= IDXGIDevice_Release(device
);
3507 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3508 refcount
= IDXGIFactory_Release(factory
);
3509 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3511 ret
= SetEvent(thread_data
.finished
);
3512 ok(ret
, "Failed to set event, last error %#lx.\n", GetLastError());
3513 ret
= WaitForSingleObject(thread
, INFINITE
);
3514 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#lx.\n", ret
, GetLastError());
3515 CloseHandle(thread
);
3516 CloseHandle(thread_data
.window_created
);
3517 CloseHandle(thread_data
.finished
);
3520 static void test_inexact_modes(void)
3522 struct swapchain_fullscreen_state initial_state
, expected_state
;
3523 DXGI_SWAP_CHAIN_DESC swapchain_desc
, result_desc
;
3524 IDXGIOutput
*output
= NULL
;
3525 IDXGISwapChain
*swapchain
;
3526 IDXGIFactory
*factory
;
3527 IDXGIAdapter
*adapter
;
3528 IDXGIDevice
*device
;
3535 unsigned int width
, height
;
3544 if (!(device
= create_device(0)))
3546 skip("Failed to create device.\n");
3550 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3551 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3553 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3554 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3556 swapchain_desc
.BufferDesc
.Width
= 800;
3557 swapchain_desc
.BufferDesc
.Height
= 600;
3558 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3559 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3560 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3561 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3562 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3563 swapchain_desc
.SampleDesc
.Count
= 1;
3564 swapchain_desc
.SampleDesc
.Quality
= 0;
3565 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3566 swapchain_desc
.BufferCount
= 1;
3567 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3568 swapchain_desc
.Windowed
= FALSE
;
3569 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3570 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
3572 memset(&initial_state
, 0, sizeof(initial_state
));
3573 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3575 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3576 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Got unexpected hr %#lx.\n", hr
);
3577 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3578 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3579 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3580 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3581 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
3582 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3583 "Got unexpected hr %#lx.\n", hr
);
3584 refcount
= IDXGISwapChain_Release(swapchain
);
3585 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3586 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3588 win_skip("GetContainingOutput() not supported.\n");
3591 if (result_desc
.Windowed
)
3593 win_skip("Fullscreen not supported.\n");
3597 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
3599 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3601 /* Test CreateSwapChain(). */
3602 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3603 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3604 swapchain_desc
.Windowed
= FALSE
;
3606 expected_state
= initial_state
;
3607 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3608 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
,
3609 sizes
[i
].width
, sizes
[i
].height
, output
);
3611 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3612 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3614 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3615 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3616 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3617 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3618 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3619 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3620 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3622 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3623 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3624 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3626 refcount
= IDXGISwapChain_Release(swapchain
);
3627 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3629 /* Test SetFullscreenState(). */
3630 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3631 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3632 swapchain_desc
.Windowed
= TRUE
;
3634 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3635 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3637 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3638 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3640 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3641 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3642 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3643 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3644 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3645 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3646 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3648 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3649 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3650 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3652 refcount
= IDXGISwapChain_Release(swapchain
);
3653 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3655 /* Test ResizeTarget(). */
3656 swapchain_desc
.BufferDesc
.Width
= 800;
3657 swapchain_desc
.BufferDesc
.Height
= 600;
3658 swapchain_desc
.Windowed
= TRUE
;
3660 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3661 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3663 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3664 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3666 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3667 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3668 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &swapchain_desc
.BufferDesc
);
3669 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3671 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3672 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3673 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3674 ok(result_desc
.BufferDesc
.Width
== 800, "Got width %u.\n", result_desc
.BufferDesc
.Width
);
3675 ok(result_desc
.BufferDesc
.Height
== 600, "Got height %u.\n", result_desc
.BufferDesc
.Height
);
3677 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3678 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3679 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3681 refcount
= IDXGISwapChain_Release(swapchain
);
3682 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3687 IDXGIOutput_Release(output
);
3688 IDXGIAdapter_Release(adapter
);
3689 refcount
= IDXGIDevice_Release(device
);
3690 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3691 refcount
= IDXGIFactory_Release(factory
);
3692 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3693 DestroyWindow(swapchain_desc
.OutputWindow
);
3696 static void test_create_factory(void)
3702 iface
= (void *)0xdeadbeef;
3703 hr
= CreateDXGIFactory(&IID_IDXGIDevice
, (void **)&iface
);
3704 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3705 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3707 hr
= CreateDXGIFactory(&IID_IUnknown
, (void **)&iface
);
3708 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3709 IUnknown_Release(iface
);
3711 hr
= CreateDXGIFactory(&IID_IDXGIObject
, (void **)&iface
);
3712 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3713 IUnknown_Release(iface
);
3715 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&iface
);
3716 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3717 check_interface(iface
, &IID_IDXGIFactory1
, FALSE
, FALSE
);
3718 IUnknown_Release(iface
);
3720 iface
= (void *)0xdeadbeef;
3721 hr
= CreateDXGIFactory(&IID_IDXGIFactory1
, (void **)&iface
);
3722 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3723 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3726 hr
= CreateDXGIFactory(&IID_IDXGIFactory2
, (void **)&iface
);
3727 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3728 "Got unexpected hr %#lx.\n", hr
);
3731 refcount
= IUnknown_Release(iface
);
3732 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3735 if (!pCreateDXGIFactory1
)
3737 win_skip("CreateDXGIFactory1 not available.\n");
3741 iface
= (void *)0xdeadbeef;
3742 hr
= pCreateDXGIFactory1(&IID_IDXGIDevice
, (void **)&iface
);
3743 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3744 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3746 hr
= pCreateDXGIFactory1(&IID_IUnknown
, (void **)&iface
);
3747 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3748 IUnknown_Release(iface
);
3750 hr
= pCreateDXGIFactory1(&IID_IDXGIObject
, (void **)&iface
);
3751 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3752 IUnknown_Release(iface
);
3754 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory
, (void **)&iface
);
3755 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3756 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3757 refcount
= IUnknown_Release(iface
);
3758 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3760 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory1
, (void **)&iface
);
3761 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3762 IUnknown_Release(iface
);
3765 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory2
, (void **)&iface
);
3766 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3767 "Got unexpected hr %#lx.\n", hr
);
3770 refcount
= IUnknown_Release(iface
);
3771 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3774 if (!pCreateDXGIFactory2
)
3776 win_skip("CreateDXGIFactory2 not available.\n");
3780 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory3
, (void **)&iface
);
3781 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3782 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3783 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3784 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3785 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3786 /* Not available on all Windows versions. */
3787 check_interface(iface
, &IID_IDXGIFactory4
, TRUE
, TRUE
);
3788 check_interface(iface
, &IID_IDXGIFactory5
, TRUE
, TRUE
);
3789 refcount
= IUnknown_Release(iface
);
3790 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3792 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory
, (void **)&iface
);
3793 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3794 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3795 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3796 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3797 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3798 refcount
= IUnknown_Release(iface
);
3799 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3802 static void test_private_data(void)
3804 ULONG refcount
, expected_refcount
;
3805 IDXGIDevice
*device
;
3807 IDXGIDevice
*test_object
;
3809 static const DWORD data
[] = {1, 2, 3, 4};
3811 static const GUID dxgi_private_data_test_guid
=
3816 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
3818 static const GUID dxgi_private_data_test_guid2
=
3823 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
3826 if (!(device
= create_device(0)))
3828 skip("Failed to create device.\n");
3832 test_object
= create_device(0);
3834 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
3835 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
3836 * NULL interface is not considered a clear but as setting an interface pointer that
3837 * happens to be NULL. */
3838 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 0, NULL
);
3839 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3840 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3841 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3842 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3843 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3844 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3845 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3847 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3848 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3849 size
= sizeof(ptr
) * 2;
3850 ptr
= (IUnknown
*)0xdeadbeef;
3851 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3852 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3853 ok(!ptr
, "Got unexpected pointer %p.\n", ptr
);
3854 ok(size
== sizeof(IUnknown
*), "Got unexpected size %u.\n", size
);
3856 refcount
= get_refcount(test_object
);
3857 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3858 (IUnknown
*)test_object
);
3859 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3860 expected_refcount
= refcount
+ 1;
3861 refcount
= get_refcount(test_object
);
3862 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3863 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3864 (IUnknown
*)test_object
);
3865 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3866 refcount
= get_refcount(test_object
);
3867 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3869 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3870 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3871 expected_refcount
--;
3872 refcount
= get_refcount(test_object
);
3873 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3875 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3876 (IUnknown
*)test_object
);
3877 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3878 size
= sizeof(data
);
3879 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, size
, data
);
3880 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3881 refcount
= get_refcount(test_object
);
3882 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3883 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3884 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3885 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3886 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3888 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3889 (IUnknown
*)test_object
);
3890 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3891 expected_refcount
++;
3892 size
= 2 * sizeof(ptr
);
3894 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3895 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3896 ok(size
== sizeof(test_object
), "Got unexpected size %u.\n", size
);
3897 expected_refcount
++;
3898 refcount
= get_refcount(test_object
);
3899 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3901 IUnknown_Release(ptr
);
3902 expected_refcount
--;
3904 ptr
= (IUnknown
*)0xdeadbeef;
3906 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3907 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3908 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3909 size
= 2 * sizeof(ptr
);
3910 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3911 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3912 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3913 refcount
= get_refcount(test_object
);
3914 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3917 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3918 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
3919 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3920 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3921 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, NULL
, NULL
);
3922 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
3924 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, &size
, &ptr
);
3925 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#lx.\n", hr
);
3926 ok(size
== 0, "Got unexpected size %u.\n", size
);
3927 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3928 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, NULL
, &ptr
);
3929 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
3930 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3932 refcount
= IDXGIDevice_Release(device
);
3933 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3934 refcount
= IDXGIDevice_Release(test_object
);
3935 ok(!refcount
, "Test object has %lu references left.\n", refcount
);
3938 #define check_surface_desc(a, b) check_surface_desc_(__LINE__, a, b)
3939 static void check_surface_desc_(unsigned int line
, IDXGISurface
*surface
,
3940 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3942 DXGI_SURFACE_DESC surface_desc
;
3945 hr
= IDXGISurface_GetDesc(surface
, &surface_desc
);
3946 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get surface desc, hr %#lx.\n", hr
);
3947 ok_(__FILE__
, line
)(surface_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3948 "Got Width %u, expected %u.\n", surface_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3949 ok_(__FILE__
, line
)(surface_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3950 "Got Height %u, expected %u.\n", surface_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3951 ok_(__FILE__
, line
)(surface_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3952 "Got Format %#x, expected %#x.\n", surface_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3953 ok_(__FILE__
, line
)(surface_desc
.SampleDesc
.Count
== 1,
3954 "Got unexpected SampleDesc.Count %u.\n", surface_desc
.SampleDesc
.Count
);
3955 ok_(__FILE__
, line
)(!surface_desc
.SampleDesc
.Quality
,
3956 "Got unexpected SampleDesc.Quality %u.\n", surface_desc
.SampleDesc
.Quality
);
3959 #define check_texture_desc(a, b) check_texture_desc_(__LINE__, a, b)
3960 static void check_texture_desc_(unsigned int line
, ID3D10Texture2D
*texture
,
3961 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3963 D3D10_TEXTURE2D_DESC texture_desc
;
3965 ID3D10Texture2D_GetDesc(texture
, &texture_desc
);
3966 ok_(__FILE__
, line
)(texture_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3967 "Got Width %u, expected %u.\n", texture_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3968 ok_(__FILE__
, line
)(texture_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3969 "Got Height %u, expected %u.\n", texture_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3970 ok_(__FILE__
, line
)(texture_desc
.MipLevels
== 1, "Got unexpected MipLevels %u.\n", texture_desc
.MipLevels
);
3971 ok_(__FILE__
, line
)(texture_desc
.ArraySize
== 1, "Got unexpected ArraySize %u.\n", texture_desc
.ArraySize
);
3972 ok_(__FILE__
, line
)(texture_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3973 "Got Format %#x, expected %#x.\n", texture_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3974 ok_(__FILE__
, line
)(texture_desc
.SampleDesc
.Count
== 1,
3975 "Got unexpected SampleDesc.Count %u.\n", texture_desc
.SampleDesc
.Count
);
3976 ok_(__FILE__
, line
)(!texture_desc
.SampleDesc
.Quality
,
3977 "Got unexpected SampleDesc.Quality %u.\n", texture_desc
.SampleDesc
.Quality
);
3978 ok_(__FILE__
, line
)(texture_desc
.Usage
== D3D10_USAGE_DEFAULT
,
3979 "Got unexpected Usage %#x.\n", texture_desc
.Usage
);
3980 ok_(__FILE__
, line
)(texture_desc
.BindFlags
== D3D10_BIND_RENDER_TARGET
,
3981 "Got unexpected BindFlags %#x.\n", texture_desc
.BindFlags
);
3982 ok_(__FILE__
, line
)(!texture_desc
.CPUAccessFlags
,
3983 "Got unexpected CPUAccessFlags %#x.\n", texture_desc
.CPUAccessFlags
);
3984 ok_(__FILE__
, line
)(!texture_desc
.MiscFlags
, "Got unexpected MiscFlags %#x.\n", texture_desc
.MiscFlags
);
3987 #define check_resource_desc(a, b) check_resource_desc_(__LINE__, a, b)
3988 static void check_resource_desc_(unsigned int line
, ID3D12Resource
*resource
,
3989 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3991 D3D12_RESOURCE_DESC resource_desc
;
3993 resource_desc
= ID3D12Resource_GetDesc(resource
);
3994 ok_(__FILE__
, line
)(resource_desc
.Dimension
== D3D12_RESOURCE_DIMENSION_TEXTURE2D
,
3995 "Got unexpected Dimension %#x.\n", resource_desc
.Dimension
);
3996 ok_(__FILE__
, line
)(resource_desc
.Width
== swapchain_desc
->BufferDesc
.Width
, "Got Width %s, expected %u.\n",
3997 wine_dbgstr_longlong(resource_desc
.Width
), swapchain_desc
->BufferDesc
.Width
);
3998 ok_(__FILE__
, line
)(resource_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3999 "Got Height %u, expected %u.\n", resource_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
4000 ok_(__FILE__
, line
)(resource_desc
.DepthOrArraySize
== 1,
4001 "Got unexpected DepthOrArraySize %u.\n", resource_desc
.DepthOrArraySize
);
4002 ok_(__FILE__
, line
)(resource_desc
.MipLevels
== 1,
4003 "Got unexpected MipLevels %u.\n", resource_desc
.MipLevels
);
4004 ok_(__FILE__
, line
)(resource_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
4005 "Got Format %#x, expected %#x.\n", resource_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
4006 ok_(__FILE__
, line
)(resource_desc
.SampleDesc
.Count
== 1,
4007 "Got unexpected SampleDesc.Count %u.\n", resource_desc
.SampleDesc
.Count
);
4008 ok_(__FILE__
, line
)(!resource_desc
.SampleDesc
.Quality
,
4009 "Got unexpected SampleDesc.Quality %u.\n", resource_desc
.SampleDesc
.Quality
);
4010 ok_(__FILE__
, line
)(resource_desc
.Layout
== D3D12_TEXTURE_LAYOUT_UNKNOWN
,
4011 "Got unexpected Layout %#x.\n", resource_desc
.Layout
);
4014 static void test_swapchain_resize(IUnknown
*device
, BOOL is_d3d12
)
4016 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4017 DXGI_SWAP_EFFECT swap_effect
;
4018 IDXGISwapChain3
*swapchain3
;
4019 IUnknown
*present_queue
[2];
4020 IDXGISwapChain
*swapchain
;
4021 ID3D12Resource
*resource
;
4022 ID3D10Texture2D
*texture
;
4023 HRESULT hr
, expected_hr
;
4024 IDXGISurface
*surface
;
4025 IDXGIFactory
*factory
;
4026 RECT client_rect
, r
;
4032 get_factory(device
, is_d3d12
, &factory
);
4034 window
= create_window();
4035 ret
= GetClientRect(window
, &client_rect
);
4036 ok(ret
, "Failed to get client rect.\n");
4038 swap_effect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4040 swapchain_desc
.BufferDesc
.Width
= 640;
4041 swapchain_desc
.BufferDesc
.Height
= 480;
4042 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4043 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
4044 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4045 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4046 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4047 swapchain_desc
.SampleDesc
.Count
= 1;
4048 swapchain_desc
.SampleDesc
.Quality
= 0;
4049 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4050 swapchain_desc
.BufferCount
= 2;
4051 swapchain_desc
.OutputWindow
= window
;
4052 swapchain_desc
.Windowed
= TRUE
;
4053 swapchain_desc
.SwapEffect
= swap_effect
;
4054 swapchain_desc
.Flags
= 0;
4056 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4057 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4058 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4059 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4060 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4061 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4062 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4063 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4064 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4065 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4066 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4067 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4068 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4070 ret
= GetClientRect(window
, &r
);
4071 ok(ret
, "Failed to get client rect.\n");
4072 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4073 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4075 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4076 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4077 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4078 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4079 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4080 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4081 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4082 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4083 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4084 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4085 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4086 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4087 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4088 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4089 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4090 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4091 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4092 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4093 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4094 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4095 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4096 ok(!swapchain_desc
.SampleDesc
.Quality
,
4097 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4098 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4099 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4100 ok(swapchain_desc
.BufferCount
== 2,
4101 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4102 ok(swapchain_desc
.OutputWindow
== window
,
4103 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4104 ok(swapchain_desc
.Windowed
,
4105 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4106 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4107 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4108 ok(!swapchain_desc
.Flags
,
4109 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4112 check_surface_desc(surface
, &swapchain_desc
);
4114 check_texture_desc(texture
, &swapchain_desc
);
4116 check_resource_desc(resource
, &swapchain_desc
);
4118 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4119 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4121 ret
= GetClientRect(window
, &r
);
4122 ok(ret
, "Failed to get client rect.\n");
4123 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4124 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4126 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4127 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4128 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4129 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4130 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4131 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4132 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4133 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4134 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4135 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4136 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4137 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4138 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4139 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4140 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4141 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4142 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4143 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4144 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4145 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4146 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4147 ok(!swapchain_desc
.SampleDesc
.Quality
,
4148 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4149 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4150 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4151 ok(swapchain_desc
.BufferCount
== 2,
4152 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4153 ok(swapchain_desc
.OutputWindow
== window
,
4154 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4155 ok(swapchain_desc
.Windowed
,
4156 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4157 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4158 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4159 ok(!swapchain_desc
.Flags
,
4160 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4164 check_surface_desc(surface
, &swapchain_desc
);
4165 IDXGISurface_Release(surface
);
4169 check_texture_desc(texture
, &swapchain_desc
);
4170 ID3D10Texture2D_Release(texture
);
4174 check_resource_desc(resource
, &swapchain_desc
);
4175 ID3D12Resource_Release(resource
);
4178 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4179 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4180 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4181 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4182 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4183 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4184 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4185 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4186 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4187 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4188 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4189 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4190 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4192 ret
= GetClientRect(window
, &r
);
4193 ok(ret
, "Failed to get client rect.\n");
4194 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4195 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4197 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4198 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4199 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4200 ok(swapchain_desc
.BufferDesc
.Width
== 320,
4201 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4202 ok(swapchain_desc
.BufferDesc
.Height
== 240,
4203 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4204 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4205 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4206 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4207 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4208 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4209 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4210 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4211 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4212 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4213 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4214 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4215 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4216 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4217 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4218 ok(!swapchain_desc
.SampleDesc
.Quality
,
4219 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4220 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4221 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4222 ok(swapchain_desc
.BufferCount
== 2,
4223 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4224 ok(swapchain_desc
.OutputWindow
== window
,
4225 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4226 ok(swapchain_desc
.Windowed
,
4227 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4228 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4229 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4230 ok(!swapchain_desc
.Flags
,
4231 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4235 check_surface_desc(surface
, &swapchain_desc
);
4236 IDXGISurface_Release(surface
);
4240 check_texture_desc(texture
, &swapchain_desc
);
4241 ID3D10Texture2D_Release(texture
);
4245 check_resource_desc(resource
, &swapchain_desc
);
4246 ID3D12Resource_Release(resource
);
4249 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4250 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4252 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4253 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4254 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4255 ok(swapchain_desc
.BufferDesc
.Width
== client_rect
.right
- client_rect
.left
,
4256 "Got unexpected BufferDesc.Width %u, expected %lu.\n",
4257 swapchain_desc
.BufferDesc
.Width
, client_rect
.right
- client_rect
.left
);
4258 ok(swapchain_desc
.BufferDesc
.Height
== client_rect
.bottom
- client_rect
.top
,
4259 "Got unexpected bufferDesc.Height %u, expected %lu.\n",
4260 swapchain_desc
.BufferDesc
.Height
, client_rect
.bottom
- client_rect
.top
);
4261 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4262 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4263 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4264 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4265 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4266 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4267 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4268 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4269 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4270 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4271 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4272 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4273 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4274 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4275 ok(!swapchain_desc
.SampleDesc
.Quality
,
4276 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4277 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4278 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4279 ok(swapchain_desc
.BufferCount
== 2,
4280 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4281 ok(swapchain_desc
.OutputWindow
== window
,
4282 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4283 ok(swapchain_desc
.Windowed
,
4284 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4285 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4286 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4287 ok(!swapchain_desc
.Flags
,
4288 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4292 present_queue
[0] = device
;
4293 present_queue
[1] = device
;
4294 if (IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
) == E_NOINTERFACE
)
4296 skip("IDXGISwapChain3 is not supported.\n");
4300 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4301 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4302 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4303 IDXGISwapChain3_Release(swapchain3
);
4307 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4308 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4309 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4310 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4311 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, present_queue
);
4312 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4313 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4314 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4315 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4316 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4319 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4320 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4321 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4322 /* Windows validates node masks even when the buffer count is zero.
4323 * It defaults to the current buffer count. NULL queues cause some
4324 * Windows versions to crash. */
4325 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240,
4326 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4327 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4328 IDXGISwapChain3_Release(swapchain3
);
4331 IDXGISwapChain_Release(swapchain
);
4332 DestroyWindow(window
);
4333 refcount
= IDXGIFactory_Release(factory
);
4334 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4337 static void test_swapchain_parameters(void)
4339 DXGI_USAGE usage
, expected_usage
, broken_usage
;
4340 D3D10_TEXTURE2D_DESC d3d10_texture_desc
;
4341 D3D11_TEXTURE2D_DESC d3d11_texture_desc
;
4342 unsigned int expected_bind_flags
;
4343 ID3D10Texture2D
*d3d10_texture
;
4344 ID3D11Texture2D
*d3d11_texture
;
4345 DXGI_SWAP_CHAIN_DESC desc
;
4346 IDXGISwapChain
*swapchain
;
4347 IDXGIResource
*resource
;
4348 IDXGIAdapter
*adapter
;
4349 IDXGIFactory
*factory
;
4350 IDXGIDevice
*device
;
4361 DXGI_SWAP_EFFECT swap_effect
;
4362 HRESULT hr
, vista_hr
;
4363 UINT highest_accessible_buffer
;
4368 {TRUE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4369 {TRUE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4370 {TRUE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4371 {TRUE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4372 {TRUE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4374 {TRUE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4375 {TRUE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4376 {TRUE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4377 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4378 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4380 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4381 {TRUE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4382 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4383 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4384 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4386 {TRUE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4387 {TRUE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4388 {TRUE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4389 {TRUE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4390 {TRUE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4392 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4393 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4394 {TRUE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4395 {FALSE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4396 {FALSE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4398 {FALSE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4399 {FALSE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4400 {FALSE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4401 {FALSE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4402 {FALSE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4404 {FALSE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4405 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4406 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4407 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4408 {FALSE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4410 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4411 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4412 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4413 {FALSE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4414 {FALSE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4416 {FALSE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4417 {FALSE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4418 {FALSE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4419 {FALSE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4420 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4422 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4424 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
4425 * process. Disable it for now.
4426 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
4429 /* The following tests crash on Win10 1909
4430 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4431 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4432 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4433 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4434 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4435 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4436 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4437 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4438 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4441 static const DXGI_USAGE usage_tests
[] =
4444 DXGI_USAGE_BACK_BUFFER
,
4445 DXGI_USAGE_SHADER_INPUT
,
4446 DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4447 DXGI_USAGE_DISCARD_ON_PRESENT
,
4448 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
,
4449 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4450 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4451 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4452 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4455 if (!(device
= create_device(0)))
4457 skip("Failed to create device.\n");
4460 window
= create_window();
4462 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
4463 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4465 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
4466 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4467 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
4468 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4469 IDXGIAdapter_Release(adapter
);
4471 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
4473 memset(&desc
, 0, sizeof(desc
));
4474 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4475 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4476 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4477 desc
.SampleDesc
.Count
= 1;
4478 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4479 desc
.OutputWindow
= window
;
4481 desc
.Windowed
= tests
[i
].windowed
;
4482 desc
.BufferCount
= tests
[i
].buffer_count
;
4483 desc
.SwapEffect
= tests
[i
].swap_effect
;
4485 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4486 ok(hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].vista_hr
)
4487 || (SUCCEEDED(tests
[i
].hr
) && hr
== DXGI_STATUS_OCCLUDED
),
4488 "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4492 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4493 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4496 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4497 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4499 IDXGISwapChain_Release(swapchain
);
4503 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4504 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4505 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4506 ok((usage
& expected_usage
) == expected_usage
, "Got usage %x, expected %x, test %u.\n",
4507 usage
, expected_usage
, i
);
4509 IDXGIResource_Release(resource
);
4511 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4512 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4514 for (j
= 1; j
<= tests
[i
].highest_accessible_buffer
; j
++)
4516 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4517 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u, buffer %u.\n", hr
, i
, j
);
4519 /* Buffers > 0 are supposed to be read only. This is the case except that in
4520 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
4521 * writable. This is not the case if an unsupported refresh rate is passed
4522 * for some reason, probably because the invalid refresh rate triggers a
4523 * kinda-sorta windowed mode.
4525 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
4528 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
4529 * the draw on the screen right away (Aero on or off doesn't matter), but
4530 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
4532 * Note that if the application doesn't have focus creating a fullscreen
4533 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
4534 * so use the Windowed property of the swapchain that was actually created. */
4535 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_READ_ONLY
;
4536 broken_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4538 if (desc
.Windowed
|| j
< tests
[i
].highest_accessible_buffer
)
4539 broken_usage
|= DXGI_USAGE_READ_ONLY
;
4541 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4542 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u, buffer %u.\n", hr
, i
, j
);
4543 ok(usage
== expected_usage
|| broken(usage
== broken_usage
),
4544 "Got usage %x, expected %x, test %u, buffer %u.\n",
4545 usage
, expected_usage
, i
, j
);
4547 IDXGIResource_Release(resource
);
4549 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4550 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4552 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4553 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4555 IDXGISwapChain_Release(swapchain
);
4558 for (i
= 0; i
< ARRAY_SIZE(usage_tests
); ++i
)
4560 usage
= usage_tests
[i
];
4562 memset(&desc
, 0, sizeof(desc
));
4563 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4564 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4565 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4566 desc
.SampleDesc
.Count
= 1;
4567 desc
.BufferUsage
= usage
;
4568 desc
.BufferCount
= 1;
4569 desc
.OutputWindow
= window
;
4570 desc
.Windowed
= TRUE
;
4571 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4572 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4573 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4575 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4576 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4577 todo_wine_if(usage
& ~(DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_SHADER_INPUT
))
4578 ok(desc
.BufferUsage
== usage
, "Got usage %#x, expected %#x, test %u.\n", desc
.BufferUsage
, usage
, i
);
4580 expected_bind_flags
= 0;
4581 if (usage
& DXGI_USAGE_RENDER_TARGET_OUTPUT
)
4582 expected_bind_flags
|= D3D11_BIND_RENDER_TARGET
;
4583 if (usage
& DXGI_USAGE_SHADER_INPUT
)
4584 expected_bind_flags
|= D3D11_BIND_SHADER_RESOURCE
;
4586 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&d3d10_texture
);
4587 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4588 ID3D10Texture2D_GetDesc(d3d10_texture
, &d3d10_texture_desc
);
4589 ok(d3d10_texture_desc
.BindFlags
== expected_bind_flags
,
4590 "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
4591 d3d10_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4592 ID3D10Texture2D_Release(d3d10_texture
);
4594 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D11Texture2D
, (void **)&d3d11_texture
);
4595 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4598 ID3D11Texture2D_GetDesc(d3d11_texture
, &d3d11_texture_desc
);
4599 ok(d3d11_texture_desc
.BindFlags
== expected_bind_flags
,
4600 "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
4601 d3d11_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4602 ID3D11Texture2D_Release(d3d11_texture
);
4605 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4606 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4609 IDXGISwapChain_Release(swapchain
);
4612 expected_usage
= usage
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
;
4613 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4614 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4615 ok(usage
== expected_usage
, "Got usage %x, expected %x, test %u.\n", usage
, expected_usage
, i
);
4616 IDXGIResource_Release(resource
);
4618 IDXGISwapChain_Release(swapchain
);
4622 memset(&desc
, 0, sizeof(desc
));
4623 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4624 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4625 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4626 desc
.SampleDesc
.Count
= 4;
4627 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4628 desc
.BufferCount
= 4;
4629 desc
.OutputWindow
= window
;
4630 desc
.Windowed
= TRUE
;
4631 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
;
4632 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4633 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4634 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
4635 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4636 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4637 if (check_multisample_quality_levels(device
, desc
.BufferDesc
.Format
, desc
.SampleDesc
.Count
))
4639 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4640 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4641 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4642 IDXGISwapChain_Release(swapchain
);
4643 desc
.SwapEffect
= DXGI_SWAP_EFFECT_SEQUENTIAL
;
4644 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4645 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4646 IDXGISwapChain_Release(swapchain
);
4650 skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM.\n");
4653 IDXGIFactory_Release(factory
);
4654 IUnknown_Release(obj
);
4655 refcount
= IDXGIDevice_Release(device
);
4656 ok(!refcount
, "Device has %lu references left.\n", refcount
);
4657 DestroyWindow(window
);
4660 static void test_swapchain_present(IUnknown
*device
, BOOL is_d3d12
)
4662 static const DWORD flags
[] = {0, DXGI_PRESENT_TEST
};
4663 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4664 IDXGISwapChain
*swapchain
;
4665 IDXGIFactory
*factory
;
4666 IDXGIOutput
*output
;
4672 get_factory(device
, is_d3d12
, &factory
);
4674 swapchain_desc
.BufferDesc
.Width
= 800;
4675 swapchain_desc
.BufferDesc
.Height
= 600;
4676 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4677 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4678 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4679 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4680 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4681 swapchain_desc
.SampleDesc
.Count
= 1;
4682 swapchain_desc
.SampleDesc
.Quality
= 0;
4683 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4684 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
4685 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
4686 swapchain_desc
.Windowed
= TRUE
;
4687 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4688 swapchain_desc
.Flags
= 0;
4690 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4691 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4693 for (i
= 0; i
< 10; ++i
)
4695 hr
= IDXGISwapChain_Present(swapchain
, i
, 0);
4696 ok(hr
== (i
<= 4 ? S_OK
: DXGI_ERROR_INVALID_CALL
),
4697 "Got unexpected hr %#lx for sync interval %u.\n", hr
, i
);
4699 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4700 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4702 for (i
= 0; i
< ARRAY_SIZE(flags
); ++i
)
4704 HWND occluding_window
= CreateWindowA("static", "occluding_window",
4705 WS_POPUP
| WS_VISIBLE
, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
4707 /* Another window covers the swapchain window. Not reported as occluded. */
4708 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4709 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4711 /* Minimised window. */
4712 ShowWindow(swapchain_desc
.OutputWindow
, SW_MINIMIZE
);
4713 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4714 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4715 ShowWindow(swapchain_desc
.OutputWindow
, SW_NORMAL
);
4717 /* Hidden window. */
4718 ShowWindow(swapchain_desc
.OutputWindow
, SW_HIDE
);
4719 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4720 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4721 ShowWindow(swapchain_desc
.OutputWindow
, SW_SHOW
);
4722 DestroyWindow(occluding_window
);
4724 /* Test that IDXGIOutput_ReleaseOwnership() makes the swapchain exit
4726 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4727 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
4728 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
4729 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
4731 skip("Test %u: Could not change fullscreen state.\n", i
);
4735 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4736 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4737 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4738 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4739 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4742 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
4743 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4744 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4745 ok(!!output
, "Test %u: Got unexpected output.\n", i
);
4748 IDXGIOutput_ReleaseOwnership(output
);
4749 /* Still fullscreen. */
4751 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4752 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4753 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4754 /* Calling IDXGISwapChain_Present() will exit fullscreen. */
4755 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4756 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4758 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4759 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4760 /* Now fullscreen mode is exited. */
4761 if (!flags
[i
] && !is_d3d12
)
4762 /* Still fullscreen on vista and 2008. */
4763 todo_wine
ok(!fullscreen
|| broken(fullscreen
), "Test %u: Got unexpected fullscreen status.\n", i
);
4765 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4767 IDXGIOutput_Release(output
);
4769 /* Test creating a window when swapchain is in fullscreen.
4771 * The window should break the swapchain out of fullscreen mode on
4772 * d3d10/11. D3d12 is different, a new occluding window doesn't break
4773 * the swapchain out of fullscreen because d3d12 fullscreen swapchains
4774 * don't take exclusive ownership over the output, nor do they disable
4775 * compositing. D3d12 fullscreen mode acts just like borderless
4776 * fullscreen window mode. */
4777 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4778 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4780 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4781 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4782 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4783 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4784 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4785 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4786 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4788 occluding_window
= CreateWindowA("static", "occluding_window", WS_POPUP
, 0, 0, 400, 200, 0, 0, 0, 0);
4789 /* An invisible window doesn't cause the swapchain to exit fullscreen
4791 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4792 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4793 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4794 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4796 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4797 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4798 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4799 /* A visible, but with bottom z-order window still causes the
4800 * swapchain to exit fullscreen mode. */
4801 SetWindowPos(occluding_window
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
4802 ShowWindow(occluding_window
, SW_SHOW
);
4803 /* Fullscreen mode takes a while to exit. */
4805 wait_fullscreen_state(swapchain
, FALSE
, TRUE
);
4807 /* No longer fullscreen before calling IDXGISwapChain_Present() except
4810 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4811 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4812 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4813 "Test %u: Got unexpected fullscreen status.\n", i
);
4815 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4816 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4817 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4818 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4819 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4822 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4823 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4824 if (flags
[i
] == DXGI_PRESENT_TEST
)
4825 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4826 "Test %u: Got unexpected fullscreen status.\n", i
);
4828 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4830 /* Even though d3d12 doesn't exit fullscreen, a
4831 * IDXGISwapChain_ResizeBuffers() is still needed for subsequent
4832 * IDXGISwapChain_Present() calls to work, otherwise they will return
4833 * DXGI_ERROR_INVALID_CALL */
4834 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4835 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4836 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4837 if (flags
[i
] == DXGI_PRESENT_TEST
)
4838 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4839 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4841 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4843 /* Trying to break out of fullscreen mode again. This time, don't call
4844 * IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */
4845 ShowWindow(occluding_window
, SW_HIDE
);
4846 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4847 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4848 ShowWindow(occluding_window
, SW_SHOW
);
4850 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4851 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4852 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4853 /* hr == S_OK on vista and 2008 */
4854 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4855 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4857 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4858 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4859 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4860 if (flags
[i
] == DXGI_PRESENT_TEST
)
4862 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4863 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4864 /* IDXGISwapChain_Present() without flags refreshes the occlusion
4866 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4867 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4868 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4869 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4870 "Test %u: Got unexpected hr %#lx.\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 %#lx.\n", i
, hr
);
4873 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
4874 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4878 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4881 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4882 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4883 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4885 DestroyWindow(occluding_window
);
4887 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4888 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4889 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4890 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4892 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4893 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4894 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4895 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4898 wait_device_idle(device
);
4900 IDXGISwapChain_Release(swapchain
);
4901 DestroyWindow(swapchain_desc
.OutputWindow
);
4902 refcount
= IDXGIFactory_Release(factory
);
4903 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4906 static void test_swapchain_backbuffer_index(IUnknown
*device
, BOOL is_d3d12
)
4908 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4909 unsigned int index
, expected_index
;
4910 IDXGISwapChain3
*swapchain3
;
4911 IDXGISwapChain
*swapchain
;
4912 HRESULT hr
, expected_hr
;
4913 IDXGIFactory
*factory
;
4919 static const DXGI_SWAP_EFFECT swap_effects
[] =
4921 DXGI_SWAP_EFFECT_DISCARD
,
4922 DXGI_SWAP_EFFECT_SEQUENTIAL
,
4923 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
,
4924 DXGI_SWAP_EFFECT_FLIP_DISCARD
,
4927 get_factory(device
, is_d3d12
, &factory
);
4929 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4930 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4931 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4932 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4933 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4934 swapchain_desc
.SampleDesc
.Count
= 1;
4935 swapchain_desc
.SampleDesc
.Quality
= 0;
4936 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4937 swapchain_desc
.BufferCount
= 4;
4938 swapchain_desc
.OutputWindow
= create_window();
4939 swapchain_desc
.Windowed
= TRUE
;
4940 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4941 swapchain_desc
.Flags
= 0;
4943 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
4944 ok(ret
, "Failed to get client rect.\n");
4945 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
4946 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
4948 for (i
= 0; i
< ARRAY_SIZE(swap_effects
); ++i
)
4950 swapchain_desc
.SwapEffect
= swap_effects
[i
];
4951 expected_hr
= is_d3d12
&& !is_flip_model(swap_effects
[i
]) ? DXGI_ERROR_INVALID_CALL
: S_OK
;
4952 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4953 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4957 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
);
4958 if (hr
== E_NOINTERFACE
)
4960 skip("IDXGISwapChain3 is not supported.\n");
4961 IDXGISwapChain_Release(swapchain
);
4965 for (j
= 0; j
< 2 * swapchain_desc
.BufferCount
; ++j
)
4967 index
= IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3
);
4968 expected_index
= is_d3d12
? j
% swapchain_desc
.BufferCount
: 0;
4969 ok(index
== expected_index
, "Got back buffer index %u, expected %u.\n", index
, expected_index
);
4970 hr
= IDXGISwapChain3_Present(swapchain3
, 0, 0);
4971 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4974 wait_device_idle(device
);
4976 IDXGISwapChain3_Release(swapchain3
);
4977 refcount
= IDXGISwapChain_Release(swapchain
);
4978 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
4982 DestroyWindow(swapchain_desc
.OutputWindow
);
4983 refcount
= IDXGIFactory_Release(factory
);
4984 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4987 static void test_swapchain_formats(IUnknown
*device
, BOOL is_d3d12
)
4989 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4990 IDXGISwapChain
*swapchain
;
4991 HRESULT hr
, expected_hr
;
4992 IDXGIFactory
*factory
;
5001 DXGI_SWAP_EFFECT swap_effect
;
5006 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_DISCARD
, FALSE
},
5007 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_SEQUENTIAL
, FALSE
},
5008 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5009 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5010 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5011 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5012 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5013 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5014 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5015 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5016 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5017 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5018 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5019 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5020 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5021 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5022 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5023 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5024 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5025 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5026 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5027 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5028 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5029 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5030 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5031 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5032 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5033 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5034 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5035 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5038 get_factory(device
, is_d3d12
, &factory
);
5040 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5041 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5042 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5043 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5044 swapchain_desc
.SampleDesc
.Count
= 1;
5045 swapchain_desc
.SampleDesc
.Quality
= 0;
5046 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5047 swapchain_desc
.BufferCount
= 4;
5048 swapchain_desc
.OutputWindow
= create_window();
5049 swapchain_desc
.Windowed
= TRUE
;
5050 swapchain_desc
.Flags
= 0;
5052 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
5053 ok(ret
, "Failed to get client rect.\n");
5054 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
5055 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
5057 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
5059 if (is_d3d12
&& !is_flip_model(tests
[i
].swap_effect
))
5062 swapchain_desc
.BufferDesc
.Format
= tests
[i
].format
;
5063 swapchain_desc
.SwapEffect
= tests
[i
].swap_effect
;
5064 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
5065 expected_hr
= tests
[i
].supported
? S_OK
: DXGI_ERROR_INVALID_CALL
;
5066 if (tests
[i
].format
== DXGI_FORMAT_UNKNOWN
&& !is_d3d12
)
5067 expected_hr
= E_INVALIDARG
;
5068 ok(hr
== expected_hr
5069 /* Flip presentation model not supported. */
5070 || broken(hr
== DXGI_ERROR_INVALID_CALL
&& is_flip_model(tests
[i
].swap_effect
) && !is_d3d12
),
5071 "Test %u, d3d12 %#x: Got unexpected hr %#lx, expected %#lx.\n", i
, is_d3d12
, hr
, expected_hr
);
5075 refcount
= IDXGISwapChain_Release(swapchain
);
5076 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
5080 DestroyWindow(swapchain_desc
.OutputWindow
);
5081 refcount
= IDXGIFactory_Release(factory
);
5082 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
5085 static void test_maximum_frame_latency(void)
5087 IDXGIDevice1
*device1
;
5088 IDXGIDevice
*device
;
5093 if (!(device
= create_device(0)))
5095 skip("Failed to create device.\n");
5099 if (SUCCEEDED(IDXGIDevice_QueryInterface(device
, &IID_IDXGIDevice1
, (void **)&device1
)))
5101 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, NULL
);
5102 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5104 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5105 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5106 ok(max_latency
== DEFAULT_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5108 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
);
5109 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5110 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5111 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5112 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5114 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
+ 1);
5115 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5116 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5117 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5118 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5120 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, 0);
5121 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5122 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5123 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5124 /* 0 does not reset to the default frame latency on all Windows versions. */
5125 ok(max_latency
== DEFAULT_FRAME_LATENCY
|| broken(!max_latency
),
5126 "Got unexpected maximum frame latency %u.\n", max_latency
);
5128 IDXGIDevice1_Release(device1
);
5132 win_skip("IDXGIDevice1 is not implemented.\n");
5135 refcount
= IDXGIDevice_Release(device
);
5136 ok(!refcount
, "Device has %lu references left.\n", refcount
);
5139 static void test_output_desc(void)
5141 IDXGIAdapter
*adapter
, *adapter2
;
5142 IDXGIOutput
*output
, *output2
;
5143 DXGI_OUTPUT_DESC desc
;
5144 IDXGIFactory
*factory
;
5149 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5150 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5154 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter
);
5155 if (hr
== DXGI_ERROR_NOT_FOUND
)
5157 winetest_push_context("Adapter %u", i
);
5158 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5160 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter2
);
5161 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5162 ok(adapter
!= adapter2
, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter
, adapter2
);
5163 refcount
= get_refcount(adapter
);
5164 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5165 IDXGIAdapter_Release(adapter2
);
5167 refcount
= get_refcount(factory
);
5168 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5169 refcount
= get_refcount(adapter
);
5170 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5174 MONITORINFOEXW monitor_info
;
5177 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output
);
5178 if (hr
== DXGI_ERROR_NOT_FOUND
)
5180 winetest_push_context("Output %u", j
);
5181 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5183 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output2
);
5184 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5185 ok(output
!= output2
, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output
, output2
);
5186 refcount
= get_refcount(output
);
5187 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5188 IDXGIOutput_Release(output2
);
5190 refcount
= get_refcount(factory
);
5191 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5192 refcount
= get_refcount(adapter
);
5193 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5194 refcount
= get_refcount(output
);
5195 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5197 hr
= IDXGIOutput_GetDesc(output
, &desc
);
5198 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5200 monitor_info
.cbSize
= sizeof(monitor_info
);
5201 ret
= GetMonitorInfoW(desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
5202 ok(ret
, "Failed to get monitor info.\n");
5203 ok(!lstrcmpW(desc
.DeviceName
, monitor_info
.szDevice
), "Got unexpected device name %s, expected %s.\n",
5204 wine_dbgstr_w(desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
5205 ok(EqualRect(&desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
5206 "Got unexpected desktop coordinates %s, expected %s.\n",
5207 wine_dbgstr_rect(&desc
.DesktopCoordinates
),
5208 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
5210 IDXGIOutput_Release(output
);
5211 refcount
= get_refcount(adapter
);
5212 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5214 winetest_pop_context();
5217 IDXGIAdapter_Release(adapter
);
5218 refcount
= get_refcount(factory
);
5219 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5221 winetest_pop_context();
5224 refcount
= IDXGIFactory_Release(factory
);
5225 ok(!refcount
, "IDXGIFactory has %lu references left.\n", refcount
);
5230 IDXGIFactory IDXGIFactory_iface
;
5231 IDXGIFactory
*wrapped_iface
;
5232 unsigned int wrapped_adapter_count
;
5235 static inline struct dxgi_factory
*impl_from_IDXGIFactory(IDXGIFactory
*iface
)
5237 return CONTAINING_RECORD(iface
, struct dxgi_factory
, IDXGIFactory_iface
);
5240 static HRESULT STDMETHODCALLTYPE
dxgi_factory_QueryInterface(IDXGIFactory
*iface
, REFIID iid
, void **out
)
5242 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5244 if (IsEqualGUID(iid
, &IID_IDXGIFactory
)
5245 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5246 || IsEqualGUID(iid
, &IID_IUnknown
))
5248 IDXGIFactory_AddRef(iface
);
5252 return IDXGIFactory_QueryInterface(factory
->wrapped_iface
, iid
, out
);
5255 static ULONG STDMETHODCALLTYPE
dxgi_factory_AddRef(IDXGIFactory
*iface
)
5257 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5258 return IDXGIFactory_AddRef(factory
->wrapped_iface
);
5261 static ULONG STDMETHODCALLTYPE
dxgi_factory_Release(IDXGIFactory
*iface
)
5263 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5264 return IDXGIFactory_Release(factory
->wrapped_iface
);
5267 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateData(IDXGIFactory
*iface
,
5268 REFGUID guid
, UINT data_size
, const void *data
)
5270 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5271 return IDXGIFactory_SetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5274 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateDataInterface(IDXGIFactory
*iface
,
5275 REFGUID guid
, const IUnknown
*object
)
5277 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5278 return IDXGIFactory_SetPrivateDataInterface(factory
->wrapped_iface
, guid
, object
);
5281 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetPrivateData(IDXGIFactory
*iface
,
5282 REFGUID guid
, UINT
*data_size
, void *data
)
5284 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5285 return IDXGIFactory_GetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5288 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetParent(IDXGIFactory
*iface
, REFIID iid
, void **parent
)
5290 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5291 return IDXGIFactory_GetParent(factory
->wrapped_iface
, iid
, parent
);
5294 static HRESULT STDMETHODCALLTYPE
dxgi_factory_EnumAdapters(IDXGIFactory
*iface
,
5295 UINT adapter_idx
, IDXGIAdapter
**adapter
)
5297 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5300 if (SUCCEEDED(hr
= IDXGIFactory_EnumAdapters(factory
->wrapped_iface
, adapter_idx
, adapter
)))
5301 ++factory
->wrapped_adapter_count
;
5305 static HRESULT STDMETHODCALLTYPE
dxgi_factory_MakeWindowAssociation(IDXGIFactory
*iface
,
5306 HWND window
, UINT flags
)
5308 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5309 return IDXGIFactory_MakeWindowAssociation(factory
->wrapped_iface
, window
, flags
);
5312 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetWindowAssociation(IDXGIFactory
*iface
, HWND
*window
)
5314 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5315 return IDXGIFactory_GetWindowAssociation(factory
->wrapped_iface
, window
);
5318 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSwapChain(IDXGIFactory
*iface
,
5319 IUnknown
*device
, DXGI_SWAP_CHAIN_DESC
*desc
, IDXGISwapChain
**swapchain
)
5321 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5322 return IDXGIFactory_CreateSwapChain(factory
->wrapped_iface
, device
, desc
, swapchain
);
5325 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSoftwareAdapter(IDXGIFactory
*iface
,
5326 HMODULE swrast
, IDXGIAdapter
**adapter
)
5328 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5329 return IDXGIFactory_CreateSoftwareAdapter(factory
->wrapped_iface
, swrast
, adapter
);
5332 static const struct IDXGIFactoryVtbl dxgi_factory_vtbl
=
5334 dxgi_factory_QueryInterface
,
5335 dxgi_factory_AddRef
,
5336 dxgi_factory_Release
,
5337 dxgi_factory_SetPrivateData
,
5338 dxgi_factory_SetPrivateDataInterface
,
5339 dxgi_factory_GetPrivateData
,
5340 dxgi_factory_GetParent
,
5341 dxgi_factory_EnumAdapters
,
5342 dxgi_factory_MakeWindowAssociation
,
5343 dxgi_factory_GetWindowAssociation
,
5344 dxgi_factory_CreateSwapChain
,
5345 dxgi_factory_CreateSoftwareAdapter
,
5350 IDXGIAdapter IDXGIAdapter_iface
;
5351 IDXGIAdapter
*wrapped_iface
;
5352 struct dxgi_factory factory
;
5353 unsigned int wrapped_output_count
;
5356 static inline struct dxgi_adapter
*impl_from_IDXGIAdapter(IDXGIAdapter
*iface
)
5358 return CONTAINING_RECORD(iface
, struct dxgi_adapter
, IDXGIAdapter_iface
);
5361 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryInterface(IDXGIAdapter
*iface
, REFIID iid
, void **out
)
5363 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5365 if (IsEqualGUID(iid
, &IID_IDXGIAdapter
)
5366 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5367 || IsEqualGUID(iid
, &IID_IUnknown
))
5369 IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5373 return IDXGIAdapter_QueryInterface(adapter
->wrapped_iface
, iid
, out
);
5376 static ULONG STDMETHODCALLTYPE
dxgi_adapter_AddRef(IDXGIAdapter
*iface
)
5378 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5379 return IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5382 static ULONG STDMETHODCALLTYPE
dxgi_adapter_Release(IDXGIAdapter
*iface
)
5384 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5385 return IDXGIAdapter_Release(adapter
->wrapped_iface
);
5388 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateData(IDXGIAdapter
*iface
,
5389 REFGUID guid
, UINT data_size
, const void *data
)
5391 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5392 return IDXGIAdapter_SetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5395 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateDataInterface(IDXGIAdapter
*iface
,
5396 REFGUID guid
, const IUnknown
*object
)
5398 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5399 return IDXGIAdapter_SetPrivateDataInterface(adapter
->wrapped_iface
, guid
, object
);
5402 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetPrivateData(IDXGIAdapter
*iface
,
5403 REFGUID guid
, UINT
*data_size
, void *data
)
5405 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5406 return IDXGIAdapter_GetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5409 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetParent(IDXGIAdapter
*iface
, REFIID iid
, void **parent
)
5411 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5412 return IDXGIFactory_QueryInterface(&adapter
->factory
.IDXGIFactory_iface
, iid
, parent
);
5415 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_EnumOutputs(IDXGIAdapter
*iface
,
5416 UINT output_idx
, IDXGIOutput
**output
)
5418 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5421 if (SUCCEEDED(hr
= IDXGIAdapter_EnumOutputs(adapter
->wrapped_iface
, output_idx
, output
)))
5422 ++adapter
->wrapped_output_count
;
5426 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc(IDXGIAdapter
*iface
, DXGI_ADAPTER_DESC
*desc
)
5428 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5429 return IDXGIAdapter_GetDesc(adapter
->wrapped_iface
, desc
);
5432 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter
*iface
,
5433 REFGUID guid
, LARGE_INTEGER
*umd_version
)
5435 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5436 return IDXGIAdapter_CheckInterfaceSupport(adapter
->wrapped_iface
, guid
, umd_version
);
5439 static const struct IDXGIAdapterVtbl dxgi_adapter_vtbl
=
5441 dxgi_adapter_QueryInterface
,
5442 dxgi_adapter_AddRef
,
5443 dxgi_adapter_Release
,
5444 dxgi_adapter_SetPrivateData
,
5445 dxgi_adapter_SetPrivateDataInterface
,
5446 dxgi_adapter_GetPrivateData
,
5447 dxgi_adapter_GetParent
,
5448 dxgi_adapter_EnumOutputs
,
5449 dxgi_adapter_GetDesc
,
5450 dxgi_adapter_CheckInterfaceSupport
,
5453 static void test_object_wrapping(void)
5455 struct dxgi_adapter wrapper
;
5456 DXGI_ADAPTER_DESC desc
;
5457 IDXGIAdapter
*adapter
;
5458 IDXGIFactory
*factory
;
5459 ID3D10Device1
*device
;
5463 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5464 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5466 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5467 if (hr
== DXGI_ERROR_NOT_FOUND
)
5469 skip("Could not enumerate adapters.\n");
5470 IDXGIFactory_Release(factory
);
5473 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5475 wrapper
.IDXGIAdapter_iface
.lpVtbl
= &dxgi_adapter_vtbl
;
5476 wrapper
.wrapped_iface
= adapter
;
5477 wrapper
.factory
.IDXGIFactory_iface
.lpVtbl
= &dxgi_factory_vtbl
;
5478 wrapper
.factory
.wrapped_iface
= factory
;
5479 wrapper
.factory
.wrapped_adapter_count
= 0;
5480 wrapper
.wrapped_output_count
= 0;
5482 hr
= D3D10CreateDevice1(&wrapper
.IDXGIAdapter_iface
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
5483 0, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
);
5486 refcount
= ID3D10Device1_Release(device
);
5487 ok(!refcount
, "Device has %lu references left.\n", refcount
);
5490 hr
= IDXGIAdapter_GetDesc(&wrapper
.IDXGIAdapter_iface
, &desc
);
5491 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5492 ok(!wrapper
.factory
.wrapped_adapter_count
, "Got unexpected wrapped adapter count %u.\n",
5493 wrapper
.factory
.wrapped_adapter_count
);
5494 ok(!wrapper
.wrapped_output_count
, "Got unexpected wrapped output count %u.\n", wrapper
.wrapped_output_count
);
5496 refcount
= IDXGIAdapter_Release(&wrapper
.IDXGIAdapter_iface
);
5497 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
5498 refcount
= IDXGIFactory_Release(factory
);
5499 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
5508 static BOOL CALLBACK
enum_monitor_proc(HMONITOR monitor
, HDC dc
, RECT
*rect
, LPARAM lparam
)
5510 struct adapter_info
*adapter_info
= (struct adapter_info
*)lparam
;
5511 MONITORINFOEXW monitor_info
;
5513 monitor_info
.cbSize
= sizeof(monitor_info
);
5514 if (GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
)
5515 && !lstrcmpiW(adapter_info
->name
, monitor_info
.szDevice
))
5517 adapter_info
->monitor
= monitor
;
5524 static HMONITOR
get_monitor(const WCHAR
*adapter_name
)
5526 struct adapter_info info
= {adapter_name
, NULL
};
5528 EnumDisplayMonitors(NULL
, NULL
, enum_monitor_proc
, (LPARAM
)&info
);
5529 return info
.monitor
;
5532 static void test_multi_adapter(void)
5534 unsigned int output_count
= 0, expected_output_count
= 0;
5535 unsigned int adapter_index
, output_index
, device_index
;
5536 DXGI_OUTPUT_DESC old_output_desc
, output_desc
;
5537 DXGI_ADAPTER_DESC1 adapter_desc1
;
5538 DXGI_ADAPTER_DESC adapter_desc
;
5539 DISPLAY_DEVICEW display_device
;
5540 MONITORINFO monitor_info
;
5541 DEVMODEW old_mode
, mode
;
5542 IDXGIAdapter1
*adapter1
;
5543 IDXGIFactory
*factory
;
5544 IDXGIAdapter
*adapter
;
5545 IDXGIOutput
*output
;
5551 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
)))
5553 skip("Failed to create IDXGIFactory, hr %#lx.\n", hr
);
5557 hr
= IDXGIFactory_EnumAdapters(factory
, 0, NULL
);
5558 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5560 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5561 if (hr
== DXGI_ERROR_NOT_FOUND
)
5563 skip("Could not enumerate adapters.\n");
5564 IDXGIFactory_Release(factory
);
5567 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5569 for (adapter_index
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)); ++adapter_index
)
5571 for (output_index
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
)); ++output_index
)
5573 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5574 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5578 display_device
.cb
= sizeof(display_device
);
5579 for (device_index
= 0; EnumDisplayDevicesW(NULL
, device_index
, &display_device
, 0); ++device_index
)
5581 if (!lstrcmpiW(display_device
.DeviceName
, output_desc
.DeviceName
))
5587 ok(found
, "Adapter %u output %u: Failed to find device %s.\n",
5588 adapter_index
, output_index
, wine_dbgstr_w(output_desc
.DeviceName
));
5590 ok(display_device
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
5591 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5592 output_index
, display_device
.StateFlags
);
5593 if (!adapter_index
&& !output_index
)
5594 ok(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
,
5595 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5596 output_index
, display_device
.StateFlags
);
5598 ok(!(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
),
5599 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5600 output_index
, display_device
.StateFlags
);
5602 /* Should have the same monitor handle. */
5603 monitor
= get_monitor(display_device
.DeviceName
);
5604 ok(!!monitor
, "Adapter %u output %u: Failed to find monitor %s.\n", adapter_index
,
5605 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5606 ok(monitor
== output_desc
.Monitor
,
5607 "Adapter %u output %u: Got unexpected monitor %p, expected %p.\n",
5608 adapter_index
, output_index
, monitor
, output_desc
.Monitor
);
5610 /* Should have the same monitor rectangle. */
5611 monitor_info
.cbSize
= sizeof(monitor_info
);
5612 ret
= GetMonitorInfoA(monitor
, &monitor_info
);
5613 ok(ret
, "Adapter %u output %u: Failed to get monitor info, error %#lx.\n", adapter_index
,
5614 output_index
, GetLastError());
5615 ok(EqualRect(&monitor_info
.rcMonitor
, &output_desc
.DesktopCoordinates
),
5616 "Adapter %u output %u: Got unexpected output rect %s, expected %s.\n",
5617 adapter_index
, output_index
, wine_dbgstr_rect(&monitor_info
.rcMonitor
),
5618 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5622 /* Test output description after it got detached */
5623 if (display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
)
5625 IDXGIOutput_Release(output
);
5629 old_output_desc
= output_desc
;
5631 /* Save current display settings */
5632 memset(&old_mode
, 0, sizeof(old_mode
));
5633 old_mode
.dmSize
= sizeof(old_mode
);
5634 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &old_mode
);
5635 /* Win10 TestBots may return FALSE but it's actually successful */
5636 ok(ret
|| broken(!ret
),
5637 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#lx.\n",
5638 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5642 memset(&mode
, 0, sizeof(mode
));
5643 mode
.dmSize
= sizeof(mode
);
5644 mode
.dmFields
= DM_POSITION
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
5645 mode
.dmPosition
= old_mode
.dmPosition
;
5646 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &mode
, NULL
,
5647 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5648 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5649 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5650 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5651 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5652 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5653 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5654 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5656 /* Check if it is really detached */
5657 memset(&mode
, 0, sizeof(mode
));
5658 mode
.dmSize
= sizeof(mode
);
5659 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &mode
);
5660 /* Win10 TestBots may return FALSE but it's actually successful */
5661 ok(ret
|| broken(!ret
) ,
5662 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#lx.\n",
5663 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5665 if (mode
.dmPelsWidth
&& mode
.dmPelsHeight
)
5667 skip("Adapter %u output %u: Failed to detach device %s.\n", adapter_index
,
5668 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5669 IDXGIOutput_Release(output
);
5673 /* Only the AttachedToDesktop field is updated after an output is detached.
5674 * IDXGIAdapter_EnumOutputs() has to be called again to get other fields updated.
5675 * But resolution changes are reflected right away. This weird behaviour is currently
5676 * unimplemented in Wine */
5677 memset(&output_desc
, 0, sizeof(output_desc
));
5678 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5679 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5681 ok(!lstrcmpiW(output_desc
.DeviceName
, old_output_desc
.DeviceName
),
5682 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5683 output_index
, wine_dbgstr_w(old_output_desc
.DeviceName
),
5684 wine_dbgstr_w(output_desc
.DeviceName
));
5686 ok(EqualRect(&output_desc
.DesktopCoordinates
, &old_output_desc
.DesktopCoordinates
),
5687 "Adapter %u output %u: Expect desktop coordinates %s, got %s.\n",
5688 adapter_index
, output_index
,
5689 wine_dbgstr_rect(&old_output_desc
.DesktopCoordinates
),
5690 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5691 ok(!output_desc
.AttachedToDesktop
,
5692 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5694 ok(output_desc
.Rotation
== old_output_desc
.Rotation
,
5695 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5696 output_index
, old_output_desc
.Rotation
, output_desc
.Rotation
);
5698 ok(output_desc
.Monitor
== old_output_desc
.Monitor
,
5699 "Adapter %u output %u: Expect monitor %p, got %p.\n", adapter_index
,
5700 output_index
, old_output_desc
.Monitor
, output_desc
.Monitor
);
5701 IDXGIOutput_Release(output
);
5703 /* Call IDXGIAdapter_EnumOutputs() again to get up-to-date output description */
5704 hr
= IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
);
5705 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5707 memset(&output_desc
, 0, sizeof(output_desc
));
5708 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5709 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5711 ok(!lstrcmpiW(output_desc
.DeviceName
, display_device
.DeviceName
),
5712 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5713 output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5714 wine_dbgstr_w(output_desc
.DeviceName
));
5715 ok(IsRectEmpty(&output_desc
.DesktopCoordinates
),
5716 "Adapter %u output %u: Expect desktop rect empty, got %s.\n", adapter_index
,
5717 output_index
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5718 ok(!output_desc
.AttachedToDesktop
,
5719 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5721 ok(output_desc
.Rotation
== DXGI_MODE_ROTATION_IDENTITY
,
5722 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5723 output_index
, DXGI_MODE_ROTATION_IDENTITY
, output_desc
.Rotation
);
5724 ok(!output_desc
.Monitor
, "Adapter %u output %u: Expect monitor NULL.\n", adapter_index
,
5727 /* Restore settings */
5728 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &old_mode
, NULL
,
5729 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5730 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5731 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5732 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5733 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5734 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5735 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5736 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5738 IDXGIOutput_Release(output
);
5741 IDXGIAdapter_Release(adapter
);
5744 /* Windows 8+ always have a WARP adapter present at the end. */
5745 todo_wine
ok(adapter_index
>= 2 || broken(adapter_index
< 2) /* Windows 7 and before */,
5746 "Got unexpected adapter count %u.\n", adapter_index
);
5747 if (adapter_index
< 2)
5749 todo_wine
win_skip("WARP adapter missing, skipping tests.\n");
5753 hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
- 1, &adapter
);
5754 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5755 hr
= IDXGIAdapter_GetDesc(adapter
, &adapter_desc
);
5756 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5757 todo_wine
ok(!lstrcmpW(adapter_desc
.Description
, L
"Microsoft Basic Render Driver"),
5758 "Got unexpected description %s.\n", wine_dbgstr_w(adapter_desc
.Description
));
5759 todo_wine
ok(adapter_desc
.VendorId
== 0x1414,
5760 "Got unexpected vendor ID %#x.\n", adapter_desc
.VendorId
);
5761 todo_wine
ok(adapter_desc
.DeviceId
== 0x008c,
5762 "Got unexpected device ID %#x.\n", adapter_desc
.DeviceId
);
5763 ok(adapter_desc
.SubSysId
== 0x0000,
5764 "Got unexpected sub-system ID %#x.\n", adapter_desc
.SubSysId
);
5765 ok(adapter_desc
.Revision
== 0x0000,
5766 "Got unexpected revision %#x.\n", adapter_desc
.Revision
);
5767 todo_wine
ok(!adapter_desc
.DedicatedVideoMemory
,
5768 "Got unexpected DedicatedVideoMemory %#Ix.\n", adapter_desc
.DedicatedVideoMemory
);
5769 ok(!adapter_desc
.DedicatedSystemMemory
,
5770 "Got unexpected DedicatedSystemMemory %#Ix.\n", adapter_desc
.DedicatedSystemMemory
);
5772 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
5773 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#lx.\n", hr
);
5776 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &adapter_desc1
);
5777 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5778 todo_wine
ok(adapter_desc1
.Flags
== DXGI_ADAPTER_FLAG_SOFTWARE
,
5779 "Got unexpected flags %#x.\n", adapter_desc1
.Flags
);
5780 IDXGIAdapter1_Release(adapter1
);
5783 IDXGIAdapter_Release(adapter
);
5786 IDXGIFactory_Release(factory
);
5788 expected_output_count
= GetSystemMetrics(SM_CMONITORS
);
5789 ok(output_count
== expected_output_count
, "Expect output count %d, got %d\n",
5790 expected_output_count
, output_count
);
5795 unsigned int message
;
5797 WPARAM expect_wparam
;
5800 static BOOL expect_no_messages
;
5801 static const struct message
*expect_messages
;
5802 static const struct message
*expect_messages_broken
;
5804 static BOOL
check_message(const struct message
*expected
,
5805 HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5807 if (expected
->message
!= message
)
5810 if (expected
->check_wparam
)
5812 ok(wparam
== expected
->expect_wparam
,
5813 "Got unexpected wparam %Ix for message %x, expected %Ix.\n",
5814 wparam
, message
, expected
->expect_wparam
);
5820 static LRESULT CALLBACK
test_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5822 ok(!expect_no_messages
, "Got unexpected message %#x, hwnd %p, wparam %#Ix, lparam %#Ix.\n",
5823 message
, hwnd
, wparam
, lparam
);
5825 if (expect_messages
)
5827 if (check_message(expect_messages
, hwnd
, message
, wparam
, lparam
))
5831 if (expect_messages_broken
)
5833 if (check_message(expect_messages_broken
, hwnd
, message
, wparam
, lparam
))
5834 ++expect_messages_broken
;
5837 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
5840 static void test_swapchain_window_messages(void)
5842 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5843 IDXGISwapChain
*swapchain
;
5844 DXGI_MODE_DESC mode_desc
;
5845 IDXGIFactory
*factory
;
5846 IDXGIAdapter
*adapter
;
5847 IDXGIDevice
*device
;
5853 static const struct message enter_fullscreen_messages
[] =
5855 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5856 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5857 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5858 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5859 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5860 {WM_GETMINMAXINFO
, FALSE
, 0},
5861 {WM_NCCALCSIZE
, FALSE
, 0},
5862 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5863 {WM_MOVE
, FALSE
, 0},
5864 {WM_SIZE
, FALSE
, 0},
5867 static const struct message enter_fullscreen_messages_vista
[] =
5869 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5870 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5871 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5872 {WM_NCCALCSIZE
, FALSE
, 0},
5873 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5874 {WM_MOVE
, FALSE
, 0},
5875 {WM_SIZE
, FALSE
, 0},
5876 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5877 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5878 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5879 {WM_GETMINMAXINFO
, FALSE
, 0},
5880 {WM_NCCALCSIZE
, FALSE
, 0},
5881 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5882 {WM_SIZE
, FALSE
, 0},
5885 static const struct message leave_fullscreen_messages
[] =
5887 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5888 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5889 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5890 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5891 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5892 {WM_GETMINMAXINFO
, FALSE
, 0},
5893 {WM_NCCALCSIZE
, FALSE
, 0},
5894 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5895 {WM_MOVE
, FALSE
, 0},
5896 {WM_SIZE
, FALSE
, 0},
5899 static const struct message resize_target_messages
[] =
5901 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5902 {WM_GETMINMAXINFO
, FALSE
, 0},
5903 {WM_NCCALCSIZE
, FALSE
, 0},
5904 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5905 {WM_SIZE
, FALSE
, 0},
5909 if (!(device
= create_device(0)))
5911 skip("Failed to create device.\n");
5915 memset(&wc
, 0, sizeof(wc
));
5916 wc
.lpfnWndProc
= test_wndproc
;
5917 wc
.lpszClassName
= "dxgi_test_wndproc_wc";
5918 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
5919 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
5920 ok(!!window
, "Failed to create window.\n");
5922 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
5923 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5924 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
5925 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5926 IDXGIAdapter_Release(adapter
);
5928 swapchain_desc
.BufferDesc
.Width
= 800;
5929 swapchain_desc
.BufferDesc
.Height
= 600;
5930 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5931 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5932 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
5933 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5934 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5935 swapchain_desc
.SampleDesc
.Count
= 1;
5936 swapchain_desc
.SampleDesc
.Quality
= 0;
5937 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5938 swapchain_desc
.BufferCount
= 1;
5939 swapchain_desc
.OutputWindow
= window
;
5940 swapchain_desc
.Windowed
= TRUE
;
5941 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
5942 swapchain_desc
.Flags
= 0;
5944 /* create swapchain */
5946 expect_no_messages
= TRUE
;
5947 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
5948 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5950 expect_no_messages
= FALSE
;
5953 expect_messages
= resize_target_messages
;
5954 memset(&mode_desc
, 0, sizeof(mode_desc
));
5955 mode_desc
.Width
= 800;
5956 mode_desc
.Height
= 600;
5957 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5958 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5960 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5962 expect_messages
= resize_target_messages
;
5963 memset(&mode_desc
, 0, sizeof(mode_desc
));
5964 mode_desc
.Width
= 400;
5965 mode_desc
.Height
= 200;
5966 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5967 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5969 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5971 /* enter fullscreen */
5972 expect_messages
= enter_fullscreen_messages
;
5973 expect_messages_broken
= enter_fullscreen_messages_vista
;
5974 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
5975 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
5976 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
5977 "Got unexpected hr %#lx.\n", hr
);
5980 skip("Could not change fullscreen state.\n");
5985 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
5986 "Expected message %#x or %#x.\n",
5987 expect_messages
->message
, expect_messages_broken
->message
);
5988 expect_messages_broken
= NULL
;
5990 /* leave fullscreen */
5991 expect_messages
= leave_fullscreen_messages
;
5992 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
5993 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5995 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5996 expect_messages
= NULL
;
5998 refcount
= IDXGISwapChain_Release(swapchain
);
5999 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6001 /* create fullscreen swapchain */
6002 DestroyWindow(window
);
6003 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6004 ok(!!window
, "Failed to create window.\n");
6005 swapchain_desc
.OutputWindow
= window
;
6006 swapchain_desc
.Windowed
= FALSE
;
6007 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6010 expect_messages
= enter_fullscreen_messages
;
6011 expect_messages_broken
= enter_fullscreen_messages_vista
;
6012 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6013 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6016 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
6017 "Expected message %#x or %#x.\n",
6018 expect_messages
->message
, expect_messages_broken
->message
);
6019 expect_messages_broken
= NULL
;
6021 /* leave fullscreen */
6022 expect_messages
= leave_fullscreen_messages
;
6023 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6024 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6026 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
6027 expect_messages
= NULL
;
6030 refcount
= IDXGISwapChain_Release(swapchain
);
6031 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6032 DestroyWindow(window
);
6034 refcount
= IDXGIDevice_Release(device
);
6035 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6036 refcount
= IDXGIFactory_Release(factory
);
6037 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6039 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
6042 static void test_swapchain_window_styles(void)
6044 LONG style
, exstyle
, fullscreen_style
, fullscreen_exstyle
;
6045 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6046 IDXGISwapChain
*swapchain
;
6047 IDXGIFactory
*factory
;
6048 IDXGIAdapter
*adapter
;
6049 IDXGIDevice
*device
;
6056 LONG style
, exstyle
;
6057 LONG expected_style
, expected_exstyle
;
6061 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
, 0,
6062 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
,
6064 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
, 0,
6065 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
| WS_VISIBLE
,
6067 {WS_OVERLAPPED
| WS_VISIBLE
, 0,
6068 WS_OVERLAPPED
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6069 {WS_OVERLAPPED
| WS_MAXIMIZE
, 0,
6070 WS_OVERLAPPED
| WS_MAXIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6071 {WS_OVERLAPPED
| WS_MINIMIZE
, 0,
6072 WS_OVERLAPPED
| WS_MINIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6073 {WS_CAPTION
| WS_DISABLED
, WS_EX_TOPMOST
,
6074 WS_CAPTION
| WS_DISABLED
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6075 {WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
, WS_EX_TOPMOST
,
6076 WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6077 {WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, WS_EX_APPWINDOW
,
6078 WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
},
6079 {WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6080 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6082 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6083 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6087 if (!(device
= create_device(0)))
6089 skip("Failed to create device.\n");
6093 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6094 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6095 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6096 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6097 IDXGIAdapter_Release(adapter
);
6099 swapchain_desc
.BufferDesc
.Width
= 800;
6100 swapchain_desc
.BufferDesc
.Height
= 600;
6101 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6102 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6103 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6104 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6105 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6106 swapchain_desc
.SampleDesc
.Count
= 1;
6107 swapchain_desc
.SampleDesc
.Quality
= 0;
6108 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6109 swapchain_desc
.BufferCount
= 1;
6110 swapchain_desc
.Windowed
= TRUE
;
6111 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6112 swapchain_desc
.Flags
= 0;
6114 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6116 winetest_push_context("Test %u", i
);
6118 swapchain_desc
.OutputWindow
= CreateWindowExA(tests
[i
].exstyle
, "static", "dxgi_test",
6119 tests
[i
].style
, 0, 0, 400, 200, 0, 0, 0, 0);
6121 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6122 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6123 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6124 style
, tests
[i
].expected_style
);
6125 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6126 exstyle
, tests
[i
].expected_exstyle
);
6128 fullscreen_style
= tests
[i
].expected_style
& ~(WS_POPUP
| WS_MAXIMIZEBOX
6129 | WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_SYSMENU
| WS_DLGFRAME
| WS_BORDER
);
6130 fullscreen_exstyle
= tests
[i
].expected_exstyle
& ~(WS_EX_DLGMODALFRAME
6131 | WS_EX_TOOLWINDOW
| WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_CONTEXTHELP
);
6132 fullscreen_exstyle
|= WS_EX_TOPMOST
;
6134 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6135 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6137 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6138 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6139 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6140 style
, tests
[i
].expected_style
);
6141 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6142 exstyle
, tests
[i
].expected_exstyle
);
6144 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6145 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6146 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6147 "Got unexpected hr %#lx.\n", hr
);
6150 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6151 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6152 todo_wine
ok(style
== fullscreen_style
, "Got unexpected style %#lx, expected %#lx.\n",
6153 style
, fullscreen_style
);
6154 ok(exstyle
== fullscreen_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6155 exstyle
, fullscreen_exstyle
);
6157 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6158 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6162 skip("Could not change fullscreen state.\n");
6165 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6166 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6167 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6168 style
, tests
[i
].expected_style
);
6169 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6170 exstyle
, tests
[i
].expected_exstyle
);
6172 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6173 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6174 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6175 "Got unexpected hr %#lx.\n", hr
);
6178 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6179 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6180 todo_wine
ok(style
== fullscreen_style
, "Got unexpected style %#lx, expected %#lx.\n",
6181 style
, fullscreen_style
);
6182 ok(exstyle
== fullscreen_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6183 exstyle
, fullscreen_exstyle
);
6185 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_STYLE
, fullscreen_style
);
6186 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
, fullscreen_exstyle
);
6188 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6189 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6191 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6192 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6193 todo_wine
ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6194 style
, tests
[i
].expected_style
);
6196 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6197 exstyle
, tests
[i
].expected_exstyle
);
6201 skip("Could not change fullscreen state.\n");
6204 refcount
= IDXGISwapChain_Release(swapchain
);
6205 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6207 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6208 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6209 todo_wine
ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6210 style
, tests
[i
].expected_style
);
6212 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6213 exstyle
, tests
[i
].expected_exstyle
);
6215 DestroyWindow(swapchain_desc
.OutputWindow
);
6217 winetest_pop_context();
6220 refcount
= IDXGIDevice_Release(device
);
6221 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6222 refcount
= IDXGIFactory_Release(factory
);
6223 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6226 static void test_gamma_control(void)
6228 DXGI_GAMMA_CONTROL_CAPABILITIES caps
;
6229 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6230 IDXGISwapChain
*swapchain
;
6231 DXGI_GAMMA_CONTROL gamma
;
6232 IDXGIFactory
*factory
;
6233 IDXGIAdapter
*adapter
;
6234 IDXGIDevice
*device
;
6235 IDXGIOutput
*output
;
6240 if (!(device
= create_device(0)))
6242 skip("Failed to create device.\n");
6246 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6247 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6249 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6250 if (hr
== DXGI_ERROR_NOT_FOUND
)
6252 skip("Adapter doesn't have any outputs.\n");
6253 IDXGIAdapter_Release(adapter
);
6254 IDXGIDevice_Release(device
);
6257 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6259 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6261 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6262 IDXGIOutput_Release(output
);
6264 swapchain_desc
.BufferDesc
.Width
= 640;
6265 swapchain_desc
.BufferDesc
.Height
= 480;
6266 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6267 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6268 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6269 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6270 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6271 swapchain_desc
.SampleDesc
.Count
= 1;
6272 swapchain_desc
.SampleDesc
.Quality
= 0;
6273 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6274 swapchain_desc
.BufferCount
= 1;
6275 swapchain_desc
.OutputWindow
= create_window();
6276 swapchain_desc
.Windowed
= TRUE
;
6277 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6278 swapchain_desc
.Flags
= 0;
6280 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6281 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6283 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6284 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6285 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6286 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6287 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6288 "Got unexpected hr %#lx.\n", hr
);
6291 skip("Could not change fullscreen state.\n");
6295 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
6296 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6298 memset(&caps
, 0, sizeof(caps
));
6299 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6300 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6302 ok(caps
.MaxConvertedValue
> caps
.MinConvertedValue
6303 || broken(caps
.MaxConvertedValue
== 0.0f
&& caps
.MinConvertedValue
== 1.0f
) /* WARP */,
6304 "Expected max gamma value (%.8e) to be bigger than min value (%.8e).\n",
6305 caps
.MaxConvertedValue
, caps
.MinConvertedValue
);
6307 for (i
= 1; i
< caps
.NumGammaControlPoints
; ++i
)
6309 ok(caps
.ControlPointPositions
[i
] > caps
.ControlPointPositions
[i
- 1],
6310 "Expected control point positions to be strictly monotonically increasing (%.8e > %.8e).\n",
6311 caps
.ControlPointPositions
[i
], caps
.ControlPointPositions
[i
- 1]);
6314 memset(&gamma
, 0, sizeof(gamma
));
6315 hr
= IDXGIOutput_GetGammaControl(output
, &gamma
);
6317 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6318 hr
= IDXGIOutput_SetGammaControl(output
, &gamma
);
6319 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6321 IDXGIOutput_Release(output
);
6323 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6324 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6327 refcount
= IDXGISwapChain_Release(swapchain
);
6328 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6329 DestroyWindow(swapchain_desc
.OutputWindow
);
6331 IDXGIAdapter_Release(adapter
);
6332 refcount
= IDXGIDevice_Release(device
);
6333 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6334 refcount
= IDXGIFactory_Release(factory
);
6335 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6338 static void test_window_association(IUnknown
*device
, BOOL is_d3d12
)
6340 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6341 LONG_PTR original_wndproc
, wndproc
;
6342 IDXGIFactory
*factory
, *factory2
;
6343 IDXGISwapChain
*swapchain
;
6344 IDXGIOutput
*output
;
6354 BOOL expect_fullscreen
;
6359 /* There are two reasons why VK_TAB and VK_ESC are not tested here:
6361 * - Posting them to the window doesn't exit fullscreen like
6362 * Alt+Enter does. Alt+Tab and Alt+Esc are handled somewhere else.
6363 * E.g., not calling IDXGISwapChain::Present() will break Alt+Tab
6364 * and Alt+Esc while Alt+Enter will still function.
6366 * - Posting them hangs the posting thread. Another thread that keeps
6367 * sending input is needed to avoid the hang. The hang is not
6368 * because of flush_events(). */
6371 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6372 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6373 {DXGI_MWA_NO_ALT_ENTER
, FALSE
, TRUE
},
6374 {DXGI_MWA_NO_ALT_ENTER
, FALSE
},
6375 {DXGI_MWA_NO_PRINT_SCREEN
, TRUE
},
6376 {DXGI_MWA_NO_PRINT_SCREEN
, FALSE
},
6381 swapchain_desc
.BufferDesc
.Width
= 640;
6382 swapchain_desc
.BufferDesc
.Height
= 480;
6383 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6384 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6385 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6386 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6387 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6388 swapchain_desc
.SampleDesc
.Count
= 1;
6389 swapchain_desc
.SampleDesc
.Quality
= 0;
6390 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6391 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6392 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6393 swapchain_desc
.Windowed
= TRUE
;
6394 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6395 swapchain_desc
.Flags
= 0;
6397 original_wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6399 hwnd2
= CreateWindowA("static", "dxgi_test2", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6400 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory2
);
6401 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6403 get_factory(device
, is_d3d12
, &factory
);
6405 hr
= IDXGIFactory_GetWindowAssociation(factory
, NULL
);
6406 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6408 for (i
= 0; i
<= DXGI_MWA_VALID
; ++i
)
6410 hr
= IDXGIFactory_MakeWindowAssociation(factory
, NULL
, i
);
6411 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6413 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, i
);
6414 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6416 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6417 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix for flags %#x.\n",
6418 wndproc
, original_wndproc
, i
);
6420 hwnd
= (HWND
)0xdeadbeef;
6421 hr
= IDXGIFactory_GetWindowAssociation(factory
, &hwnd
);
6422 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6423 /* Apparently GetWindowAssociation() always returns NULL, even when
6424 * MakeWindowAssociation() and GetWindowAssociation() are both
6425 * successfully called. */
6426 ok(!hwnd
, "Expect null associated window.\n");
6429 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, DXGI_MWA_VALID
+ 1);
6430 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6432 /* Alt+Enter tests. */
6433 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6434 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6436 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6437 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix.\n", wndproc
, original_wndproc
);
6439 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6440 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6441 || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Windows 7 testbot */,
6442 "Got unexpected hr %#lx.\n", hr
);
6445 skip("Could not change fullscreen state.\n");
6449 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6450 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6452 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6454 winetest_push_context("Test %u", i
);
6456 /* First associate a window with the opposite flags. */
6457 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6458 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6460 /* Associate the current test window. */
6461 hwnd
= tests
[i
].flag
? swapchain_desc
.OutputWindow
: NULL
;
6462 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd
, tests
[i
].flag
);
6463 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6465 /* Associating a new test window doesn't override the old window. */
6466 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6467 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6469 /* Associations with a different factory don't affect the existing
6471 hr
= IDXGIFactory_MakeWindowAssociation(factory2
, hwnd
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6472 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6474 /* Post synthesized Alt + VK_RETURN WM_SYSKEYDOWN. */
6475 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
6476 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
6479 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
6480 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6481 ok(fullscreen
== tests
[i
].expect_fullscreen
6482 || broken(tests
[i
].broken_d3d10
&& fullscreen
),
6483 "Got unexpected fullscreen %#x.\n", fullscreen
);
6484 ok(fullscreen
? !!output
: !output
, "Got unexpected output.\n");
6486 IDXGIOutput_Release(output
);
6488 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6489 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix.\n",
6490 wndproc
, original_wndproc
);
6492 winetest_pop_context();
6496 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6497 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6499 refcount
= IDXGIFactory_Release(factory2
);
6500 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6501 DestroyWindow(hwnd2
);
6503 refcount
= IDXGISwapChain_Release(swapchain
);
6504 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6505 DestroyWindow(swapchain_desc
.OutputWindow
);
6507 refcount
= IDXGIFactory_Release(factory
);
6508 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
6511 static void test_output_ownership(IUnknown
*device
, BOOL is_d3d12
)
6513 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc
;
6514 D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_ownership_desc
;
6515 D3DKMT_CLOSEADAPTER close_adapter_desc
;
6516 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6517 DXGI_OUTPUT_DESC output_desc
;
6518 IDXGISwapChain
*swapchain
;
6519 IDXGIFactory
*factory
;
6520 IDXGIAdapter
*adapter
;
6521 IDXGIOutput
*output
;
6527 if (!pD3DKMTCheckVidPnExclusiveOwnership
6528 || pD3DKMTCheckVidPnExclusiveOwnership(NULL
) == STATUS_PROCEDURE_NOT_FOUND
)
6530 win_skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n");
6534 get_factory(device
, is_d3d12
, &factory
);
6535 adapter
= get_adapter(device
, is_d3d12
);
6538 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
6539 IDXGIFactory_Release(factory
);
6543 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6544 IDXGIAdapter_Release(adapter
);
6545 if (hr
== DXGI_ERROR_NOT_FOUND
)
6547 skip("Adapter doesn't have any outputs.\n");
6548 IDXGIFactory_Release(factory
);
6551 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6553 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6554 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6556 lstrcpyW(open_adapter_gdi_desc
.DeviceName
, output_desc
.DeviceName
);
6557 status
= pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc
);
6558 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
6560 check_ownership_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6561 check_ownership_desc
.VidPnSourceId
= open_adapter_gdi_desc
.VidPnSourceId
;
6562 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6563 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6566 swapchain_desc
.BufferDesc
.Width
= 800;
6567 swapchain_desc
.BufferDesc
.Height
= 600;
6568 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6569 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6570 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6571 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6572 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6573 swapchain_desc
.SampleDesc
.Count
= 1;
6574 swapchain_desc
.SampleDesc
.Quality
= 0;
6575 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6576 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6577 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
6578 swapchain_desc
.Windowed
= TRUE
;
6579 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6580 swapchain_desc
.Flags
= 0;
6581 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6582 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6584 /* Swapchain in fullscreen mode. */
6585 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
6586 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
6587 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
6588 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
6590 skip("Failed to change fullscreen state.\n");
6593 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6595 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6596 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6597 ok(fullscreen
, "Got unexpected fullscreen state.\n");
6598 /* Win10 1909 doesn't seem to grab output exclusive ownership.
6599 * And all output ownership calls return S_OK on D3D10 and D3D12 with 1909. */
6602 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6603 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6608 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6609 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6610 todo_wine
ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6611 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6612 "Got unexpected status %#lx, expected %#lx.\n", status
,
6613 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6615 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, FALSE
);
6616 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6617 "Got unexpected hr %#lx.\n", hr
);
6618 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, TRUE
);
6619 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6620 "Got unexpected hr %#lx.\n", hr
);
6621 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6623 todo_wine
ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6625 todo_wine
ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
), /* Win10 1909 */
6626 "Got unexpected hr %#lx.\n", hr
);
6627 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6628 ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6629 IDXGIOutput_ReleaseOwnership(output
);
6630 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6631 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6634 /* IDXGIOutput_TakeOwnership always returns E_NOINTERFACE for d3d12. Tests
6639 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6640 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6641 "Got unexpected hr %#lx.\n", hr
);
6642 IDXGIOutput_ReleaseOwnership(output
);
6644 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6645 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6646 /* Note that the "exclusive" parameter to IDXGIOutput_TakeOwnership()
6647 * seems to behave opposite to what's described by MSDN. */
6648 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6649 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6650 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6651 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6652 "Got unexpected status %#lx, expected %#lx.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6653 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6654 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Win10 1909 */, "Got unexpected hr %#lx.\n", hr
);
6655 IDXGIOutput_ReleaseOwnership(output
);
6657 /* Swapchain in windowed mode. */
6658 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6659 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6661 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6662 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6663 ok(!fullscreen
, "Unexpected fullscreen state.\n");
6664 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6665 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6668 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6669 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6670 "Got unexpected hr %#lx.\n", hr
);
6672 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6673 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6674 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6675 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6676 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
|| broken(hr
== S_OK
), /* Win10 1909 */
6677 "Got unexpected status %#lx, expected %#lx.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6678 IDXGIOutput_ReleaseOwnership(output
);
6679 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6680 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6684 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6685 wait_device_idle(device
);
6687 IDXGIOutput_Release(output
);
6688 IDXGISwapChain_Release(swapchain
);
6689 DestroyWindow(swapchain_desc
.OutputWindow
);
6690 refcount
= IDXGIFactory_Release(factory
);
6691 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
6693 close_adapter_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6694 status
= pD3DKMTCloseAdapter(&close_adapter_desc
);
6695 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
6698 static void test_cursor_clipping(IUnknown
*device
, BOOL is_d3d12
)
6700 unsigned int adapter_idx
, output_idx
, mode_idx
, mode_count
;
6701 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6702 DXGI_OUTPUT_DESC output_desc
;
6703 IDXGIAdapter
*adapter
= NULL
;
6704 RECT virtual_rect
, clip_rect
;
6705 unsigned int width
, height
;
6706 IDXGISwapChain
*swapchain
;
6707 DXGI_MODE_DESC
*modes
;
6708 IDXGIFactory
*factory
;
6709 IDXGIOutput
*output
;
6714 get_factory(device
, is_d3d12
, &factory
);
6716 swapchain_desc
.SampleDesc
.Count
= 1;
6717 swapchain_desc
.SampleDesc
.Quality
= 0;
6718 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6719 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6720 swapchain_desc
.Windowed
= TRUE
;
6721 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6722 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6724 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
6727 winetest_push_context("Adapter %u", adapter_idx
);
6729 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
6732 winetest_push_context("Output %u", output_idx
);
6734 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
6735 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 TestBots */
6736 "Got unexpected hr %#lx.\n", hr
);
6737 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
6739 win_skip("GetDisplayModeList() not supported.\n");
6740 IDXGIOutput_Release(output
);
6741 winetest_pop_context();
6745 modes
= heap_calloc(mode_count
, sizeof(*modes
));
6746 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
6747 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6749 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6750 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6751 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
6752 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
6753 for (mode_idx
= 0; mode_idx
< mode_count
; ++mode_idx
)
6755 if (modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
)
6758 ok(modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
,
6759 "Failed to find a different mode than %ux%u.\n", width
, height
);
6761 ret
= ClipCursor(NULL
);
6762 ok(ret
, "ClipCursor failed, error %#lx.\n", GetLastError());
6763 get_virtual_rect(&virtual_rect
);
6764 ret
= GetClipCursor(&clip_rect
);
6765 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6766 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6767 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6769 swapchain_desc
.BufferDesc
.Width
= modes
[mode_idx
].Width
;
6770 swapchain_desc
.BufferDesc
.Height
= modes
[mode_idx
].Height
;
6771 swapchain_desc
.BufferDesc
.RefreshRate
= modes
[mode_idx
].RefreshRate
;
6772 swapchain_desc
.BufferDesc
.Format
= modes
[mode_idx
].Format
;
6773 swapchain_desc
.BufferDesc
.ScanlineOrdering
= modes
[mode_idx
].ScanlineOrdering
;
6774 swapchain_desc
.BufferDesc
.Scaling
= modes
[mode_idx
].Scaling
;
6775 swapchain_desc
.OutputWindow
= create_window();
6777 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6778 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6781 get_virtual_rect(&virtual_rect
);
6782 ret
= GetClipCursor(&clip_rect
);
6783 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6784 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6785 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6787 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6788 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6789 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6790 "Got unexpected hr %#lx.\n", hr
);
6793 skip("Could not change fullscreen state, hr %#lx.\n", hr
);
6794 IDXGISwapChain_Release(swapchain
);
6795 IDXGIOutput_Release(output
);
6796 DestroyWindow(swapchain_desc
.OutputWindow
);
6797 winetest_pop_context();
6802 get_virtual_rect(&virtual_rect
);
6803 ret
= GetClipCursor(&clip_rect
);
6804 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6805 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6806 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6808 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6809 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6810 refcount
= IDXGISwapChain_Release(swapchain
);
6811 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6812 refcount
= IDXGIOutput_Release(output
);
6813 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
6814 DestroyWindow(swapchain_desc
.OutputWindow
);
6817 get_virtual_rect(&virtual_rect
);
6818 ret
= GetClipCursor(&clip_rect
);
6819 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6820 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6821 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6823 winetest_pop_context();
6826 IDXGIAdapter_Release(adapter
);
6828 winetest_pop_context();
6831 refcount
= IDXGIFactory_Release(factory
);
6832 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
6835 static void test_factory_check_feature_support(void)
6837 IDXGIFactory5
*factory
;
6842 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory5
, (void**)&factory
)))
6844 win_skip("IDXGIFactory5 is not available.\n");
6848 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, 0x12345678, (void *)&data
, sizeof(data
));
6849 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6851 /* Crashes on Windows. */
6854 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, NULL
, sizeof(data
));
6855 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6858 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) - 1);
6859 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6861 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) + 1);
6862 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6864 data
= (BOOL
)0xdeadbeef;
6865 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
));
6866 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6867 ok(data
== TRUE
|| data
== FALSE
, "Got unexpected data %#x.\n", data
);
6869 ref_count
= IDXGIFactory5_Release(factory
);
6870 ok(!ref_count
, "Factory has %lu references left.\n", ref_count
);
6873 static void test_frame_latency_event(IUnknown
*device
, BOOL is_d3d12
)
6875 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
6876 IDXGISwapChain2
*swapchain2
;
6877 IDXGISwapChain1
*swapchain1
;
6878 IDXGIFactory2
*factory2
;
6879 IDXGIFactory
*factory
;
6888 get_factory(device
, is_d3d12
, &factory
);
6890 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
6891 IDXGIFactory_Release(factory
);
6894 win_skip("IDXGIFactory2 not available.\n");
6898 window
= create_window();
6900 swapchain_desc
.Width
= 640;
6901 swapchain_desc
.Height
= 480;
6902 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6903 swapchain_desc
.Stereo
= FALSE
;
6904 swapchain_desc
.SampleDesc
.Count
= 1;
6905 swapchain_desc
.SampleDesc
.Quality
= 0;
6906 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6907 swapchain_desc
.BufferCount
= 2;
6908 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
6909 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
6910 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
6911 swapchain_desc
.Flags
= 0;
6913 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6914 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6915 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6917 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6918 IDXGISwapChain1_Release(swapchain1
);
6921 win_skip("IDXGISwapChain2 not available.\n");
6922 IDXGIFactory2_Release(factory2
);
6923 DestroyWindow(window
);
6927 /* test swap chain without waitable object */
6928 frame_latency
= 0xdeadbeef;
6929 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6930 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6931 ok(frame_latency
== 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency
);
6932 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 1);
6933 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6934 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6935 ok(!event
, "Got unexpected event %p.\n", event
);
6937 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6938 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
6940 /* test swap chain with waitable object */
6941 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
;
6943 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6944 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6945 ok(hr
== S_OK
, "Failed to create swap chain, hr %#lx.\n", hr
);
6946 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6947 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6948 IDXGISwapChain1_Release(swapchain1
);
6950 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6951 ok(!!event
, "Got unexpected event %p.\n", event
);
6953 /* auto-reset event */
6954 wait_result
= WaitForSingleObject(event
, 0);
6955 ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6956 wait_result
= WaitForSingleObject(event
, 0);
6957 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6959 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6960 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6961 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6963 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 0);
6964 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6965 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6966 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6967 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6969 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 3);
6970 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6971 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6972 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6973 ok(frame_latency
== 3, "Got unexpected frame latency %#x.\n", frame_latency
);
6975 wait_result
= WaitForSingleObject(event
, 0);
6976 todo_wine
ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6977 wait_result
= WaitForSingleObject(event
, 0);
6978 todo_wine
ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6979 wait_result
= WaitForSingleObject(event
, 100);
6980 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6982 for (i
= 0; i
< 5; i
++)
6984 hr
= IDXGISwapChain2_Present(swapchain2
, 0, 0);
6985 ok(hr
== S_OK
, "Present %u failed with hr %#lx.\n", i
, hr
);
6987 wait_result
= WaitForSingleObject(event
, 100);
6988 ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6991 wait_result
= WaitForSingleObject(event
, 100);
6992 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6994 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6995 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
6996 DestroyWindow(window
);
6997 ref_count
= IDXGIFactory2_Release(factory2
);
6998 ok(ref_count
== !is_d3d12
, "Factory has %lu references left.\n", ref_count
);
7001 static void test_colour_space_support(IUnknown
*device
, BOOL is_d3d12
)
7003 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
7004 IDXGISwapChain3
*swapchain3
;
7005 IDXGISwapChain1
*swapchain1
;
7006 IDXGIFactory2
*factory2
;
7007 IDXGIFactory
*factory
;
7014 static const DXGI_COLOR_SPACE_TYPE colour_spaces
[] =
7016 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
,
7017 DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
,
7018 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
,
7019 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
,
7020 DXGI_COLOR_SPACE_RESERVED
,
7021 DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
,
7022 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
,
7023 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
,
7024 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
,
7025 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
,
7026 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
,
7027 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
,
7028 DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
,
7029 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
,
7030 DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
,
7031 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
,
7032 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
,
7033 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
,
7034 DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
,
7035 DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
,
7038 get_factory(device
, is_d3d12
, &factory
);
7040 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
7041 IDXGIFactory_Release(factory
);
7044 win_skip("IDXGIFactory2 not available.\n");
7048 window
= create_window();
7050 swapchain_desc
.Width
= 640;
7051 swapchain_desc
.Height
= 480;
7052 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7053 swapchain_desc
.Stereo
= FALSE
;
7054 swapchain_desc
.SampleDesc
.Count
= 1;
7055 swapchain_desc
.SampleDesc
.Quality
= 0;
7056 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7057 swapchain_desc
.BufferCount
= 2;
7058 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
7059 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
7060 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
7061 swapchain_desc
.Flags
= 0;
7063 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
7064 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
7065 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7067 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain3
, (void**)&swapchain3
);
7068 IDXGISwapChain1_Release(swapchain1
);
7071 win_skip("IDXGISwapChain3 not available.\n");
7072 IDXGIFactory2_Release(factory2
);
7073 DestroyWindow(window
);
7077 for (i
= 0; i
< ARRAY_SIZE(colour_spaces
); ++i
)
7079 support
= 0xdeadbeef;
7080 hr
= IDXGISwapChain3_CheckColorSpaceSupport(swapchain3
, colour_spaces
[i
], &support
);
7081 ok(hr
== S_OK
, "Got unexpected hr %#lx for test %u.\n", hr
, i
);
7082 ok(!(support
& ~DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
),
7083 "Got unexpected support flags %#x for test %u.\n", support
, i
);
7085 if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
)
7087 ok(support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
,
7088 "Required colour space not supported for test %u.\n", i
);
7090 else if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RESERVED
)
7092 ok(!support
, "Invalid colour space supported for test %u.\n", i
);
7095 hr
= IDXGISwapChain3_SetColorSpace1(swapchain3
, colour_spaces
[i
]);
7096 ok(hr
== (support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
) ? S_OK
: E_INVALIDARG
,
7097 "Got unexpected hr %#lx for text %u.\n", hr
, i
);
7100 ref_count
= IDXGISwapChain3_Release(swapchain3
);
7101 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
7102 DestroyWindow(window
);
7103 ref_count
= IDXGIFactory2_Release(factory2
);
7104 ok(ref_count
== !is_d3d12
, "Factory has %lu references left.\n", ref_count
);
7107 static void test_mode_change(IUnknown
*device
, BOOL is_d3d12
)
7109 unsigned int user32_width
= 0, user32_height
= 0, d3d_width
= 0, d3d_height
= 0;
7110 unsigned int display_count
= 0, mode_idx
= 0, adapter_idx
, output_idx
;
7111 DEVMODEW
*original_modes
= NULL
, old_devmode
, devmode
, devmode2
;
7112 DXGI_SWAP_CHAIN_DESC swapchain_desc
, swapchain_desc2
;
7113 IDXGIOutput
*output
, *second_output
= NULL
;
7114 WCHAR second_monitor_name
[CCHDEVICENAME
];
7115 IDXGISwapChain
*swapchain
, *swapchain2
;
7116 DXGI_OUTPUT_DESC output_desc
;
7117 IDXGIAdapter
*adapter
;
7118 IDXGIFactory
*factory
;
7119 BOOL fullscreen
, ret
;
7124 memset(&devmode
, 0, sizeof(devmode
));
7125 devmode
.dmSize
= sizeof(devmode
);
7126 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode
);
7127 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7128 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7129 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode
);
7130 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7131 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7133 while (EnumDisplaySettingsW(NULL
, mode_idx
++, &devmode
))
7135 if (devmode
.dmPelsWidth
== registry_mode
.dmPelsWidth
7136 && devmode
.dmPelsHeight
== registry_mode
.dmPelsHeight
)
7139 if (!d3d_width
&& !d3d_height
)
7141 d3d_width
= devmode
.dmPelsWidth
;
7142 d3d_height
= devmode
.dmPelsHeight
;
7146 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7149 user32_width
= devmode
.dmPelsWidth
;
7150 user32_height
= devmode
.dmPelsHeight
;
7153 if (!user32_width
|| !user32_height
)
7155 skip("Failed to find three different display modes for the primary output.\n");
7159 ret
= save_display_modes(&original_modes
, &display_count
);
7160 ok(ret
, "Failed to save original display modes.\n");
7162 get_factory(device
, is_d3d12
, &factory
);
7164 /* Test that no mode restorations if no mode changes actually happened */
7165 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7166 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7168 swapchain_desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
7169 swapchain_desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
7170 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
7171 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
7172 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7173 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
7174 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
7175 swapchain_desc
.SampleDesc
.Count
= 1;
7176 swapchain_desc
.SampleDesc
.Quality
= 0;
7177 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7178 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
7179 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
7180 swapchain_desc
.Windowed
= TRUE
;
7181 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
7182 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
7184 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7185 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7186 refcount
= IDXGISwapChain_Release(swapchain
);
7187 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7189 memset(&devmode2
, 0, sizeof(devmode2
));
7190 devmode2
.dmSize
= sizeof(devmode2
);
7191 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7192 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7193 ok(equal_mode_rect(&devmode2
, ®istry_mode
), "Got a different mode.\n");
7194 ret
= restore_display_modes(original_modes
, display_count
);
7195 ok(ret
, "Failed to restore display modes.\n");
7197 /* If current display settings are different than the display settings in registry before
7198 * calling SetFullscreenState() */
7199 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7200 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7202 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7203 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7204 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7205 ok(hr
== DXGI_ERROR_UNSUPPORTED
/* Win7 */
7206 || hr
== S_OK
/* Win8~Win10 1909 */
7207 || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, /* Win10 2004 */
7208 "Got unexpected hr %#lx.\n", hr
);
7210 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7211 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7212 refcount
= IDXGISwapChain_Release(swapchain
);
7213 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7214 ret
= restore_display_modes(original_modes
, display_count
);
7215 ok(ret
, "Failed to restore display modes.\n");
7217 /* Test that mode restorations use display settings in the registry with a fullscreen device */
7218 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7219 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7220 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7223 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
7224 refcount
= IDXGISwapChain_Release(swapchain
);
7225 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7229 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7230 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7231 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7232 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7234 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7235 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7236 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7237 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7238 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7239 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7240 refcount
= IDXGISwapChain_Release(swapchain
);
7241 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7242 ret
= restore_display_modes(original_modes
, display_count
);
7243 ok(ret
, "Failed to restore display modes.\n");
7245 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
)); ++adapter_idx
)
7247 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
)); ++output_idx
)
7249 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
7250 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
7252 if ((adapter_idx
|| output_idx
) && output_desc
.AttachedToDesktop
)
7254 second_output
= output
;
7258 IDXGIOutput_Release(output
);
7261 IDXGIAdapter_Release(adapter
);
7268 skip("Following tests require two monitors.\n");
7271 lstrcpyW(second_monitor_name
, output_desc
.DeviceName
);
7273 memset(&old_devmode
, 0, sizeof(old_devmode
));
7274 old_devmode
.dmSize
= sizeof(old_devmode
);
7275 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &old_devmode
);
7276 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7283 while (EnumDisplaySettingsW(second_monitor_name
, mode_idx
++, &devmode
))
7285 if (devmode
.dmPelsWidth
== old_devmode
.dmPelsWidth
7286 && devmode
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7289 if (!d3d_width
&& !d3d_height
)
7291 d3d_width
= devmode
.dmPelsWidth
;
7292 d3d_height
= devmode
.dmPelsHeight
;
7296 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7299 user32_width
= devmode
.dmPelsWidth
;
7300 user32_height
= devmode
.dmPelsHeight
;
7303 if (!user32_width
|| !user32_height
)
7305 skip("Failed to find three different display modes for the second output.\n");
7309 /* Test that mode restorations for non-primary outputs upon fullscreen state changes */
7310 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7311 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7312 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7313 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7315 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
, CDS_RESET
, NULL
);
7316 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret
);
7317 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7318 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7319 if (devmode2
.dmPelsWidth
== old_devmode
.dmPelsWidth
7320 && devmode2
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7322 skip("Failed to change display settings of the second monitor.\n");
7323 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7324 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7325 refcount
= IDXGISwapChain_Release(swapchain
);
7326 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7330 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7331 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7333 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7334 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7335 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7336 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7337 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7338 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7339 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7340 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7341 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7342 old_devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", old_devmode
.dmPelsWidth
,
7343 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7344 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7345 old_devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", old_devmode
.dmPelsHeight
,
7346 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7348 refcount
= IDXGISwapChain_Release(swapchain
);
7349 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7350 ret
= restore_display_modes(original_modes
, display_count
);
7351 ok(ret
, "Failed to restore display modes.\n");
7353 /* Test that mode restorations for non-primary outputs use display settings in the registry */
7354 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7355 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7356 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7357 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7359 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
,
7360 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
7361 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret
);
7362 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7363 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7365 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7366 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7367 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7368 "Expected resolution %lux%lu, got %lux%lu.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7369 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7370 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7371 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7372 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7373 "Expected resolution %lux%lu, got %lux%lu.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7374 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7375 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7376 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7377 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7378 devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", devmode
.dmPelsWidth
,
7379 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7380 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7381 devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", devmode
.dmPelsHeight
,
7382 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7384 refcount
= IDXGISwapChain_Release(swapchain
);
7385 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7386 ret
= restore_display_modes(original_modes
, display_count
);
7387 ok(ret
, "Failed to restore display modes.\n");
7389 /* Test that mode restorations for non-primary outputs on fullscreen state changes when there
7390 * are two fullscreen swapchains on different outputs */
7391 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7392 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7394 swapchain_desc2
= swapchain_desc
;
7395 swapchain_desc
.BufferDesc
.Width
= d3d_width
;
7396 swapchain_desc
.BufferDesc
.Height
= d3d_height
;
7397 swapchain_desc2
.OutputWindow
= CreateWindowA("static", "dxgi_test2", 0,
7398 old_devmode
.dmPosition
.x
, old_devmode
.dmPosition
.y
, 400, 200, 0, 0, 0, 0);
7399 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc2
, &swapchain2
);
7400 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7401 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7402 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7403 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, TRUE
, NULL
);
7406 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
7407 refcount
= IDXGISwapChain_Release(swapchain2
);
7408 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7409 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7410 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7411 refcount
= IDXGISwapChain_Release(swapchain
);
7412 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7416 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7417 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7418 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
7419 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7420 ok(!fullscreen
, "Expected swapchain not fullscreen.\n");
7421 hr
= IDXGISwapChain_GetFullscreenState(swapchain2
, &fullscreen
, NULL
);
7422 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7423 ok(fullscreen
, "Expected swapchain fullscreen.\n");
7425 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7426 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7427 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7428 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7429 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7430 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7431 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7432 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7433 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7434 old_devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", old_devmode
.dmPelsWidth
,
7435 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7436 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7437 old_devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", old_devmode
.dmPelsHeight
,
7438 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7440 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, FALSE
, NULL
);
7441 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7442 refcount
= IDXGISwapChain_Release(swapchain2
);
7443 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7444 refcount
= IDXGISwapChain_Release(swapchain
);
7445 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7446 DestroyWindow(swapchain_desc2
.OutputWindow
);
7447 ret
= restore_display_modes(original_modes
, display_count
);
7448 ok(ret
, "Failed to restore display modes.\n");
7452 IDXGIOutput_Release(second_output
);
7453 DestroyWindow(swapchain_desc
.OutputWindow
);
7454 refcount
= IDXGIFactory_Release(factory
);
7455 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
7456 ret
= restore_display_modes(original_modes
, display_count
);
7457 ok(ret
, "Failed to restore display modes.\n");
7458 heap_free(original_modes
);
7461 static void test_swapchain_present_count(IUnknown
*device
, BOOL is_d3d12
)
7463 UINT present_count
, expected
;
7464 IDXGISwapChain
*swapchain
;
7468 window
= create_window();
7469 swapchain
= create_swapchain(device
, is_d3d12
, window
);
7471 present_count
= ~0u;
7472 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7473 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7474 ok(!present_count
, "Got unexpected present count %u.\n", present_count
);
7476 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7477 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7478 expected
= present_count
+ 1;
7479 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7480 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7481 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7483 hr
= IDXGISwapChain_Present(swapchain
, 10, 0);
7484 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
7485 expected
= present_count
;
7486 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7487 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7488 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7490 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
7491 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7492 expected
= present_count
;
7493 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7494 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7495 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7497 ShowWindow(window
, SW_MINIMIZE
);
7498 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7499 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Got unexpected hr %#lx.\n", hr
);
7500 expected
= present_count
+ !!is_d3d12
;
7501 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7502 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7503 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7505 ShowWindow(window
, SW_NORMAL
);
7506 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7507 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7508 expected
= present_count
+ 1;
7509 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7510 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7511 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7513 IDXGISwapChain_Release(swapchain
);
7514 DestroyWindow(window
);
7517 static void run_on_d3d10(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7519 IDXGIDevice
*device
;
7522 if (!(device
= create_device(0)))
7524 skip("Failed to create Direct3D 10 device.\n");
7528 test_func((IUnknown
*)device
, FALSE
);
7530 refcount
= IDXGIDevice_Release(device
);
7531 ok(!refcount
, "Device has %lu references left.\n", refcount
);
7534 static void run_on_d3d12(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7536 ID3D12CommandQueue
*queue
;
7537 ID3D12Device
*device
;
7540 if (!(device
= create_d3d12_device()))
7542 skip("Failed to create Direct3D 12 device.\n");
7546 queue
= create_d3d12_direct_queue(device
);
7548 test_func((IUnknown
*)queue
, TRUE
);
7550 wait_queue_idle(device
, queue
);
7552 refcount
= ID3D12CommandQueue_Release(queue
);
7553 ok(!refcount
, "Command queue has %lu references left.\n", refcount
);
7554 refcount
= ID3D12Device_Release(device
);
7555 ok(!refcount
, "Device has %lu references left.\n", refcount
);
7560 HMODULE dxgi_module
, d3d11_module
, d3d12_module
, gdi32_module
;
7561 BOOL enable_debug_layer
= FALSE
;
7562 unsigned int argc
, i
;
7566 dxgi_module
= GetModuleHandleA("dxgi.dll");
7567 pCreateDXGIFactory1
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory1");
7568 pCreateDXGIFactory2
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory2");
7570 gdi32_module
= GetModuleHandleA("gdi32.dll");
7571 pD3DKMTCheckVidPnExclusiveOwnership
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCheckVidPnExclusiveOwnership");
7572 pD3DKMTCloseAdapter
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCloseAdapter");
7573 pD3DKMTOpenAdapterFromGdiDisplayName
= (void *)GetProcAddress(gdi32_module
, "D3DKMTOpenAdapterFromGdiDisplayName");
7575 d3d11_module
= LoadLibraryA("d3d11.dll");
7576 pD3D11CreateDevice
= (void *)GetProcAddress(d3d11_module
, "D3D11CreateDevice");
7578 registry_mode
.dmSize
= sizeof(registry_mode
);
7579 ok(EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, ®istry_mode
), "Failed to get display mode.\n");
7581 use_mt
= !getenv("WINETEST_NO_MT_D3D");
7582 /* Some host drivers (MacOS, Mesa radeonsi) never unmap memory even when
7583 * requested. When using the chunk allocator, running the tests with more
7584 * than one thread can exceed the 32-bit virtual address space. */
7585 if (sizeof(void *) == 4 && !strcmp(winetest_platform
, "wine"))
7588 argc
= winetest_get_mainargs(&argv
);
7589 for (i
= 2; i
< argc
; ++i
)
7591 if (!strcmp(argv
[i
], "--validate"))
7592 enable_debug_layer
= TRUE
;
7593 else if (!strcmp(argv
[i
], "--warp"))
7594 use_warp_adapter
= TRUE
;
7595 else if (!strcmp(argv
[i
], "--adapter") && i
+ 1 < argc
)
7596 use_adapter_idx
= atoi(argv
[++i
]);
7597 else if (!strcmp(argv
[i
], "--single"))
7601 queue_test(test_adapter_desc
);
7602 queue_test(test_adapter_luid
);
7603 queue_test(test_query_video_memory_info
);
7604 queue_test(test_check_interface_support
);
7605 queue_test(test_create_surface
);
7606 queue_test(test_parents
);
7607 queue_test(test_output
);
7608 queue_test(test_find_closest_matching_mode
);
7609 queue_test(test_resize_target_wndproc
);
7610 queue_test(test_create_factory
);
7611 queue_test(test_private_data
);
7612 queue_test(test_maximum_frame_latency
);
7613 queue_test(test_output_desc
);
7614 queue_test(test_object_wrapping
);
7615 queue_test(test_factory_check_feature_support
);
7619 /* These tests use full-screen swapchains, so shouldn't run in parallel. */
7620 test_create_swapchain();
7621 test_inexact_modes();
7622 test_gamma_control();
7623 test_multi_adapter();
7624 test_swapchain_parameters();
7625 test_swapchain_window_messages();
7626 test_swapchain_window_styles();
7627 run_on_d3d10(test_set_fullscreen
);
7628 run_on_d3d10(test_resize_target
);
7629 run_on_d3d10(test_swapchain_resize
);
7630 run_on_d3d10(test_swapchain_present
);
7631 run_on_d3d10(test_swapchain_backbuffer_index
);
7632 run_on_d3d10(test_swapchain_formats
);
7633 run_on_d3d10(test_output_ownership
);
7634 run_on_d3d10(test_cursor_clipping
);
7635 run_on_d3d10(test_get_containing_output
);
7636 run_on_d3d10(test_window_association
);
7637 run_on_d3d10(test_default_fullscreen_target_output
);
7638 run_on_d3d10(test_mode_change
);
7639 run_on_d3d10(test_swapchain_present_count
);
7641 if (!(d3d12_module
= LoadLibraryA("d3d12.dll")))
7643 skip("Direct3D 12 is not available.\n");
7647 pD3D12CreateDevice
= (void *)GetProcAddress(d3d12_module
, "D3D12CreateDevice");
7648 pD3D12GetDebugInterface
= (void *)GetProcAddress(d3d12_module
, "D3D12GetDebugInterface");
7650 if (enable_debug_layer
&& SUCCEEDED(pD3D12GetDebugInterface(&IID_ID3D12Debug
, (void **)&debug
)))
7652 ID3D12Debug_EnableDebugLayer(debug
);
7653 ID3D12Debug_Release(debug
);
7656 run_on_d3d12(test_set_fullscreen
);
7657 run_on_d3d12(test_resize_target
);
7658 run_on_d3d12(test_swapchain_resize
);
7659 run_on_d3d12(test_swapchain_present
);
7660 run_on_d3d12(test_swapchain_backbuffer_index
);
7661 run_on_d3d12(test_swapchain_formats
);
7662 run_on_d3d12(test_output_ownership
);
7663 run_on_d3d12(test_cursor_clipping
);
7664 run_on_d3d12(test_frame_latency_event
);
7665 run_on_d3d12(test_colour_space_support
);
7666 run_on_d3d12(test_get_containing_output
);
7667 run_on_d3d12(test_window_association
);
7668 run_on_d3d12(test_default_fullscreen_target_output
);
7669 run_on_d3d12(test_mode_change
);
7670 run_on_d3d12(test_swapchain_present_count
);
7672 FreeLibrary(d3d12_module
);