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_IDXGIResource
, TRUE
, FALSE
);
1269 check_interface(surface
, &IID_ID3D10Texture2D
, TRUE
, FALSE
);
1270 /* Not available on all Windows versions. */
1271 check_interface(surface
, &IID_ID3D11Texture2D
, TRUE
, TRUE
);
1272 /* Not available on all Windows versions. */
1273 check_interface(surface
, &IID_IDXGISurface1
, TRUE
, TRUE
);
1275 IDXGISurface_Release(surface
);
1276 refcount
= IDXGIDevice_Release(device
);
1277 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1279 /* DXGI_USAGE_UNORDERED_ACCESS */
1280 if (!(device
= create_d3d11_device()))
1282 skip("Failed to create D3D11 device.\n");
1287 hr
= IDXGIDevice_CreateSurface(device
, &desc
, 1, DXGI_USAGE_UNORDERED_ACCESS
, NULL
, &surface
);
1288 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1292 ID3D11UnorderedAccessView
*uav
;
1293 ID3D11Device
*d3d_device
;
1295 hr
= IDXGISurface_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture2d
);
1296 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1298 ID3D11Texture2D_GetDevice(texture2d
, &d3d_device
);
1300 hr
= ID3D11Device_CreateUnorderedAccessView(d3d_device
, (ID3D11Resource
*)texture2d
, NULL
, &uav
);
1301 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1302 ID3D11UnorderedAccessView_Release(uav
);
1304 ID3D11Device_Release(d3d_device
);
1305 ID3D11Texture2D_Release(texture2d
);
1307 IDXGISurface_Release(surface
);
1310 refcount
= IDXGIDevice_Release(device
);
1311 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1314 static void test_parents(void)
1316 DXGI_SURFACE_DESC surface_desc
;
1317 IDXGISurface
*surface
;
1318 IDXGIFactory
*factory
;
1319 IDXGIAdapter
*adapter
;
1320 IDXGIDevice
*device
;
1321 IDXGIOutput
*output
;
1326 if (!(device
= create_device(0)))
1328 skip("Failed to create device.\n");
1332 surface_desc
.Width
= 512;
1333 surface_desc
.Height
= 512;
1334 surface_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1335 surface_desc
.SampleDesc
.Count
= 1;
1336 surface_desc
.SampleDesc
.Quality
= 0;
1338 hr
= IDXGIDevice_CreateSurface(device
, &surface_desc
, 1, DXGI_USAGE_RENDER_TARGET_OUTPUT
, NULL
, &surface
);
1339 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1341 hr
= IDXGISurface_GetParent(surface
, &IID_IDXGIDevice
, (void **)&parent
);
1342 IDXGISurface_Release(surface
);
1343 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1344 ok(parent
== (IUnknown
*)device
, "Got parent %p, expected %p.\n", parent
, device
);
1345 IUnknown_Release(parent
);
1347 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1348 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1350 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1351 if (hr
== DXGI_ERROR_NOT_FOUND
)
1353 skip("Adapter has not outputs.\n");
1357 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1359 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&parent
);
1360 IDXGIOutput_Release(output
);
1361 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1362 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1363 IUnknown_Release(parent
);
1366 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1367 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1369 hr
= IDXGIFactory_GetParent(factory
, &IID_IUnknown
, (void **)&parent
);
1370 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
1371 ok(parent
== NULL
, "Got parent %p, expected %p.\n", parent
, NULL
);
1372 IDXGIFactory_Release(factory
);
1374 hr
= IDXGIDevice_GetParent(device
, &IID_IDXGIAdapter
, (void **)&parent
);
1375 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1376 ok(parent
== (IUnknown
*)adapter
, "Got parent %p, expected %p.\n", parent
, adapter
);
1377 IUnknown_Release(parent
);
1379 IDXGIAdapter_Release(adapter
);
1380 refcount
= IDXGIDevice_Release(device
);
1381 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1384 static void test_output(void)
1386 unsigned int mode_count
, mode_count_comp
, i
, last_height
, last_width
;
1387 double last_refresh_rate
;
1388 IDXGIAdapter
*adapter
;
1389 IDXGIDevice
*device
;
1391 IDXGIOutput
*output
;
1393 DXGI_MODE_DESC
*modes
;
1395 if (!(device
= create_device(0)))
1397 skip("Failed to create device.\n");
1401 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1402 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1404 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, NULL
);
1405 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1407 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1408 if (hr
== DXGI_ERROR_NOT_FOUND
)
1410 skip("Adapter doesn't have any outputs.\n");
1411 IDXGIAdapter_Release(adapter
);
1412 IDXGIDevice_Release(device
);
1415 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1417 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, NULL
, NULL
);
1418 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1420 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1421 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Remote Desktop Services / Win 7 testbot */
1422 "Got unexpected hr %#lx.\n", hr
);
1423 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1425 win_skip("GetDisplayModeList() not supported.\n");
1426 IDXGIOutput_Release(output
);
1427 IDXGIAdapter_Release(adapter
);
1428 IDXGIDevice_Release(device
);
1431 mode_count_comp
= mode_count
;
1433 hr
= IDXGIOutput_GetDisplayModeList(output
, 0, 0, &mode_count
, NULL
);
1434 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1435 ok(!mode_count
, "Got unexpected mode_count %u.\n", mode_count
);
1437 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1438 DXGI_ENUM_MODES_SCALING
, &mode_count
, NULL
);
1439 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1440 ok(mode_count
>= mode_count_comp
, "Got unexpected mode_count %u, expected >= %u.\n", mode_count
, mode_count_comp
);
1441 mode_count_comp
= mode_count
;
1443 modes
= heap_calloc(mode_count
+ 10, sizeof(*modes
));
1444 ok(!!modes
, "Failed to allocate memory.\n");
1446 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1447 DXGI_ENUM_MODES_SCALING
, NULL
, modes
);
1448 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1449 ok(!modes
[0].Height
, "No output was expected.\n");
1452 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1453 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1454 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
1455 ok(!modes
[0].Height
, "No output was expected.\n");
1457 mode_count
= mode_count_comp
;
1458 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1459 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1460 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1461 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1463 last_width
= last_height
= 0;
1464 last_refresh_rate
= 0.;
1465 for (i
= 0; i
< mode_count
; i
++)
1467 double refresh_rate
= modes
[i
].RefreshRate
.Numerator
/ (double)modes
[i
].RefreshRate
.Denominator
;
1469 ok(modes
[i
].Width
&& modes
[i
].Height
, "Mode %u: Invalid dimensions %ux%u.\n",
1470 i
, modes
[i
].Width
, modes
[i
].Height
);
1472 ok(modes
[i
].Width
>= last_width
,
1473 "Mode %u: Modes should have been sorted, width %u < %u.\n", i
, modes
[i
].Width
, last_width
);
1474 if (modes
[i
].Width
!= last_width
)
1476 last_width
= modes
[i
].Width
;
1478 last_refresh_rate
= 0.;
1482 ok(modes
[i
].Height
>= last_height
,
1483 "Mode %u: Modes should have been sorted, height %u < %u.\n", i
, modes
[i
].Height
, last_height
);
1484 if (modes
[i
].Height
!= last_height
)
1486 last_height
= modes
[i
].Height
;
1487 last_refresh_rate
= 0.;
1491 ok(refresh_rate
>= last_refresh_rate
,
1492 "Mode %u: Modes should have been sorted, refresh rate %f < %f.\n", i
, refresh_rate
, last_refresh_rate
);
1493 if (refresh_rate
!= last_refresh_rate
)
1494 last_refresh_rate
= refresh_rate
;
1498 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1499 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1500 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1501 ok(mode_count
== mode_count_comp
, "Got unexpected mode_count %u, expected %u.\n", mode_count
, mode_count_comp
);
1503 if (mode_count_comp
)
1505 mode_count
= mode_count_comp
- 1;
1506 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
,
1507 DXGI_ENUM_MODES_SCALING
, &mode_count
, modes
);
1508 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
1509 ok(mode_count
== mode_count_comp
- 1, "Got unexpected mode_count %u, expected %u.\n",
1510 mode_count
, mode_count_comp
- 1);
1514 skip("Not enough modes for test.\n");
1518 IDXGIOutput_Release(output
);
1519 IDXGIAdapter_Release(adapter
);
1520 refcount
= IDXGIDevice_Release(device
);
1521 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1524 static void test_find_closest_matching_mode(void)
1526 static const DXGI_MODE_SCALING scaling_tests
[] =
1528 DXGI_MODE_SCALING_CENTERED
,
1529 DXGI_MODE_SCALING_STRETCHED
1531 DXGI_MODE_DESC
*modes
, mode
, matching_mode
;
1532 unsigned int i
, j
, mode_count
;
1533 IDXGIAdapter
*adapter
;
1534 IDXGIDevice
*device
;
1535 IDXGIOutput
*output
;
1539 if (!(device
= create_device(0)))
1541 skip("Failed to create device.\n");
1545 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1546 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1548 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
1549 if (hr
== DXGI_ERROR_NOT_FOUND
)
1551 win_skip("Adapter doesn't have any outputs.\n");
1552 IDXGIAdapter_Release(adapter
);
1553 IDXGIDevice_Release(device
);
1556 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1558 memset(&mode
, 0, sizeof(mode
));
1559 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1560 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
1561 "Got unexpected hr %#lx.\n", hr
);
1562 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
1564 win_skip("FindClosestMatchingMode() not supported.\n");
1568 memset(&mode
, 0, sizeof(mode
));
1569 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, (IUnknown
*)device
);
1570 todo_wine
ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1572 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
1573 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1575 modes
= heap_calloc(mode_count
, sizeof(*modes
));
1576 ok(!!modes
, "Failed to allocate memory.\n");
1578 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
1579 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1581 for (i
= 0; i
< mode_count
; ++i
)
1584 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1585 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1586 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
);
1588 mode
.Format
= DXGI_FORMAT_UNKNOWN
;
1589 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1590 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1594 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1595 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1599 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1600 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1603 mode
.Width
= mode
.Height
= 0;
1604 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1605 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1606 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_RESOLUTION
);
1607 ok(matching_mode
.Width
> 0 && matching_mode
.Height
> 0, "Got unexpected resolution %ux%u.\n",
1608 matching_mode
.Width
, matching_mode
.Height
);
1611 mode
.RefreshRate
.Numerator
= mode
.RefreshRate
.Denominator
= 0;
1612 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1613 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1614 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_REFRESH_RATE
);
1615 ok(matching_mode
.RefreshRate
.Numerator
> 0 && matching_mode
.RefreshRate
.Denominator
> 0,
1616 "Got unexpected refresh rate %u / %u.\n",
1617 matching_mode
.RefreshRate
.Numerator
, matching_mode
.RefreshRate
.Denominator
);
1620 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1621 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1622 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1623 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_IGNORE_SCALING
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1624 ok(matching_mode
.ScanlineOrdering
, "Got unexpected scanline ordering %#x.\n",
1625 matching_mode
.ScanlineOrdering
);
1627 memset(&mode
, 0, sizeof(mode
));
1628 mode
.Width
= modes
[i
].Width
;
1629 mode
.Height
= modes
[i
].Height
;
1630 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1631 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1632 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1633 check_mode_desc(&matching_mode
, &modes
[i
], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1635 memset(&mode
, 0, sizeof(mode
));
1636 mode
.Width
= modes
[i
].Width
- 1;
1637 mode
.Height
= modes
[i
].Height
- 1;
1638 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1639 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1640 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1641 check_mode_desc(&matching_mode
, &modes
[i
],
1642 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1644 memset(&mode
, 0, sizeof(mode
));
1645 mode
.Width
= modes
[i
].Width
+ 1;
1646 mode
.Height
= modes
[i
].Height
+ 1;
1647 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1648 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1649 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1650 check_mode_desc(&matching_mode
, &modes
[i
],
1651 (MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
) | MODE_DESC_IGNORE_EXACT_RESOLUTION
);
1654 memset(&mode
, 0, sizeof(mode
));
1655 mode
.Width
= mode
.Height
= 10;
1656 mode
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1657 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1658 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1659 /* Find mode for the lowest resolution. */
1661 for (i
= 0; i
< mode_count
; ++i
)
1663 if (mode
.Width
>= modes
[i
].Width
&& mode
.Height
>= modes
[i
].Height
)
1666 check_mode_desc(&matching_mode
, &mode
, MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1668 memset(&mode
, 0, sizeof(mode
));
1669 mode
.Width
= modes
[0].Width
;
1670 mode
.Height
= modes
[0].Height
;
1671 mode
.Format
= modes
[0].Format
;
1672 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UPPER_FIELD_FIRST
;
1673 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1674 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1675 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1677 memset(&mode
, 0, sizeof(mode
));
1678 mode
.Width
= modes
[0].Width
;
1679 mode
.Height
= modes
[0].Height
;
1680 mode
.Format
= modes
[0].Format
;
1681 mode
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_LOWER_FIELD_FIRST
;
1682 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1683 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1684 check_mode_desc(&matching_mode
, &modes
[0], MODE_DESC_CHECK_RESOLUTION
& MODE_DESC_CHECK_FORMAT
);
1686 for (i
= 0; i
< ARRAY_SIZE(scaling_tests
); ++i
)
1688 for (j
= 0; j
< mode_count
; ++j
)
1690 if (modes
[j
].Scaling
!= scaling_tests
[i
])
1693 memset(&mode
, 0, sizeof(mode
));
1694 mode
.Width
= modes
[j
].Width
;
1695 mode
.Height
= modes
[j
].Height
;
1696 mode
.Format
= modes
[j
].Format
;
1697 mode
.Scaling
= modes
[j
].Scaling
;
1698 hr
= IDXGIOutput_FindClosestMatchingMode(output
, &mode
, &matching_mode
, NULL
);
1699 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1700 check_mode_desc(&matching_mode
, &modes
[j
],
1701 MODE_DESC_IGNORE_REFRESH_RATE
| MODE_DESC_IGNORE_SCANLINE_ORDERING
);
1709 IDXGIOutput_Release(output
);
1710 IDXGIAdapter_Release(adapter
);
1711 refcount
= IDXGIDevice_Release(device
);
1712 ok(!refcount
, "Device has %lu references left.\n", refcount
);
1715 struct refresh_rates
1719 BOOL numerator_should_pass
;
1720 BOOL denominator_should_pass
;
1723 static void test_create_swapchain(void)
1725 struct swapchain_fullscreen_state initial_state
, expected_state
;
1726 unsigned int i
, expected_width
, expected_height
;
1727 DXGI_SWAP_CHAIN_DESC creation_desc
, result_desc
;
1728 DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc
;
1729 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
1730 IDXGIDevice
*device
, *bgra_device
;
1731 ULONG refcount
, expected_refcount
;
1732 IUnknown
*obj
, *obj2
, *parent
;
1733 IDXGISwapChain1
*swapchain1
;
1734 RECT
*expected_client_rect
;
1735 IDXGISwapChain
*swapchain
;
1736 IDXGISurface1
*surface
;
1737 IDXGIAdapter
*adapter
;
1738 IDXGIFactory
*factory
;
1739 IDXGIOutput
*target
;
1744 const struct refresh_rates refresh_list
[] =
1746 {60, 60, FALSE
, FALSE
},
1747 {60, 0, TRUE
, FALSE
},
1748 {60, 1, TRUE
, TRUE
},
1749 { 0, 60, TRUE
, FALSE
},
1750 { 0, 0, TRUE
, FALSE
},
1753 if (!(device
= create_device(0)))
1755 skip("Failed to create device.\n");
1759 creation_desc
.BufferDesc
.Width
= 800;
1760 creation_desc
.BufferDesc
.Height
= 600;
1761 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
1762 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
1763 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1764 creation_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
1765 creation_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
1766 creation_desc
.SampleDesc
.Count
= 1;
1767 creation_desc
.SampleDesc
.Quality
= 0;
1768 creation_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
1769 creation_desc
.BufferCount
= 1;
1770 creation_desc
.OutputWindow
= NULL
;
1771 creation_desc
.Windowed
= TRUE
;
1772 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
1773 creation_desc
.Flags
= 0;
1775 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
1776 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1778 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
1779 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1781 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
1782 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1784 expected_refcount
= get_refcount(adapter
);
1785 refcount
= get_refcount(factory
);
1786 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1787 refcount
= get_refcount(device
);
1788 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1790 creation_desc
.OutputWindow
= NULL
;
1791 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1792 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1794 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
1795 memset(&initial_state
, 0, sizeof(initial_state
));
1796 capture_fullscreen_state(&initial_state
.fullscreen_state
, creation_desc
.OutputWindow
);
1798 hr
= IDXGIFactory_CreateSwapChain(factory
, NULL
, &creation_desc
, &swapchain
);
1799 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1800 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, NULL
, &swapchain
);
1801 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1802 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, NULL
);
1803 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
1804 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1805 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1807 refcount
= get_refcount(adapter
);
1808 ok(refcount
>= expected_refcount
, "Got refcount %lu, expected >= %lu.\n", refcount
, expected_refcount
);
1809 refcount
= get_refcount(factory
);
1810 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1811 refcount
= get_refcount(device
);
1812 ok(refcount
== 3, "Got unexpected refcount %lu.\n", refcount
);
1814 hr
= IDXGISwapChain_GetDesc(swapchain
, NULL
);
1815 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1817 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IUnknown
, (void **)&parent
);
1818 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1819 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1820 refcount
= IUnknown_Release(parent
);
1821 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1823 hr
= IDXGISwapChain_GetParent(swapchain
, &IID_IDXGIFactory
, (void **)&parent
);
1824 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1825 ok(parent
== (IUnknown
*)factory
, "Got unexpected parent interface pointer %p.\n", parent
);
1826 refcount
= IUnknown_Release(parent
);
1827 todo_wine
ok(refcount
== 4, "Got unexpected refcount %lu.\n", refcount
);
1829 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain1
, (void **)&swapchain1
);
1830 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
1831 "Got unexpected hr %#lx.\n", hr
);
1834 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, NULL
);
1835 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1836 hr
= IDXGISwapChain1_GetDesc1(swapchain1
, &swapchain_desc
);
1837 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1838 ok(!swapchain_desc
.Stereo
, "Got unexpected stereo %#x.\n", swapchain_desc
.Stereo
);
1839 ok(swapchain_desc
.Scaling
== DXGI_SCALING_STRETCH
,
1840 "Got unexpected scaling %#x.\n", swapchain_desc
.Scaling
);
1841 ok(swapchain_desc
.AlphaMode
== DXGI_ALPHA_MODE_IGNORE
,
1842 "Got unexpected alpha mode %#x.\n", swapchain_desc
.AlphaMode
);
1843 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, NULL
);
1844 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
1845 hr
= IDXGISwapChain1_GetFullscreenDesc(swapchain1
, &fullscreen_desc
);
1846 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1847 ok(fullscreen_desc
.Windowed
== creation_desc
.Windowed
,
1848 "Got unexpected windowed %#x.\n", fullscreen_desc
.Windowed
);
1849 hr
= IDXGISwapChain1_GetHwnd(swapchain1
, &window
);
1850 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1851 ok(window
== creation_desc
.OutputWindow
, "Got unexpected window %p.\n", window
);
1852 IDXGISwapChain1_Release(swapchain1
);
1855 refcount
= IDXGISwapChain_Release(swapchain
);
1856 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
1858 refcount
= get_refcount(factory
);
1859 ok(refcount
== 2, "Got unexpected refcount %lu.\n", refcount
);
1861 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1863 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1864 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1866 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1867 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1869 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1870 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1872 ok(result_desc
.Windowed
== creation_desc
.Windowed
, "Test %u: Got unexpected windowed %#x.\n",
1873 i
, result_desc
.Windowed
);
1875 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1876 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1877 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1879 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1880 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1881 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1883 fullscreen
= 0xdeadbeef;
1884 target
= (void *)0xdeadbeef;
1885 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1886 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1887 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1888 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1890 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
1891 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1892 fullscreen
= 0xdeadbeef;
1893 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
1894 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1895 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
1896 target
= (void *)0xdeadbeef;
1897 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
1898 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1899 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1901 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
1902 IDXGISwapChain_Release(swapchain
);
1905 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
1907 /* Test GDI-compatible swapchain */
1908 bgra_device
= create_device(D3D10_CREATE_DEVICE_BGRA_SUPPORT
);
1909 ok(!!bgra_device
, "Failed to create BGRA capable device.\n");
1911 hr
= IDXGIDevice_QueryInterface(bgra_device
, &IID_IUnknown
, (void **)&obj2
);
1912 ok(hr
== S_OK
, "IDXGIDevice does not implement IUnknown.\n");
1914 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1915 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1917 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1922 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1923 ok(FAILED(hr
), "Got unexpected hr %#lx.\n", hr
);
1925 IDXGISurface1_Release(surface
);
1926 IDXGISwapChain_Release(swapchain
);
1928 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
1929 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE
;
1931 hr
= IDXGIFactory_CreateSwapChain(factory
, obj2
, &creation_desc
, &swapchain
);
1932 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1934 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
1935 creation_desc
.Flags
= 0;
1937 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface1
, (void **)&surface
);
1938 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1940 hr
= IDXGISurface1_GetDC(surface
, FALSE
, &hdc
);
1941 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
1942 IDXGISurface1_ReleaseDC(surface
, NULL
);
1944 IDXGISurface1_Release(surface
);
1945 IDXGISwapChain_Release(swapchain
);
1949 win_skip("IDXGISurface1 is not supported, skipping GetDC() tests.\n");
1950 IDXGISwapChain_Release(swapchain
);
1952 IUnknown_Release(obj2
);
1953 IDXGIDevice_Release(bgra_device
);
1955 creation_desc
.Windowed
= FALSE
;
1957 for (i
= 0; i
< ARRAY_SIZE(refresh_list
); ++i
)
1959 creation_desc
.BufferDesc
.RefreshRate
.Numerator
= refresh_list
[i
].numerator
;
1960 creation_desc
.BufferDesc
.RefreshRate
.Denominator
= refresh_list
[i
].denominator
;
1962 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
1963 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1965 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
1966 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1968 /* When numerator is non-zero and denominator is zero, the windowed mode is used.
1969 * Additionally, some versions of WARP seem to always fail to change fullscreen state. */
1970 if (result_desc
.Windowed
!= creation_desc
.Windowed
)
1971 trace("Test %u: Failed to change fullscreen state.\n", i
);
1973 todo_wine_if (!refresh_list
[i
].numerator_should_pass
)
1974 ok(result_desc
.BufferDesc
.RefreshRate
.Numerator
== refresh_list
[i
].numerator
,
1975 "Numerator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Numerator
);
1977 todo_wine_if (!refresh_list
[i
].denominator_should_pass
)
1978 ok(result_desc
.BufferDesc
.RefreshRate
.Denominator
== refresh_list
[i
].denominator
,
1979 "Denominator %u is %u.\n", i
, result_desc
.BufferDesc
.RefreshRate
.Denominator
);
1983 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
1984 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1985 ok(fullscreen
== !result_desc
.Windowed
, "Test %u: Got fullscreen %#x, expected %#x.\n",
1986 i
, fullscreen
, result_desc
.Windowed
);
1987 ok(result_desc
.Windowed
? !target
: !!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
1988 if (!result_desc
.Windowed
)
1990 IDXGIOutput
*containing_output
;
1991 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
1992 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
1993 ok(containing_output
== target
, "Test %u: Got unexpected containing output pointer %p.\n",
1994 i
, containing_output
);
1995 IDXGIOutput_Release(containing_output
);
1997 ok(output_belongs_to_adapter(target
, adapter
),
1998 "Test %u: Output %p doesn't belong to adapter %p.\n",
1999 i
, target
, adapter
);
2000 IDXGIOutput_Release(target
);
2002 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, NULL
);
2003 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2005 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2006 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2007 ok(fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2009 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2010 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2011 ok(!!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2012 IDXGIOutput_Release(target
);
2015 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2016 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2018 fullscreen
= 0xdeadbeef;
2019 target
= (void *)0xdeadbeef;
2020 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &target
);
2021 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
2022 ok(!fullscreen
, "Test %u: Got unexpected fullscreen %#x.\n", i
, fullscreen
);
2023 ok(!target
, "Test %u: Got unexpected target %p.\n", i
, target
);
2025 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2026 IDXGISwapChain_Release(swapchain
);
2029 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2031 /* Test swapchain creation with DXGI_FORMAT_UNKNOWN. */
2032 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_UNKNOWN
;
2033 creation_desc
.Windowed
= TRUE
;
2034 creation_desc
.Flags
= 0;
2035 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2036 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
2038 creation_desc
.Windowed
= FALSE
;
2039 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2040 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
2042 creation_desc
.BufferCount
= 2;
2043 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
2044 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2045 ok(hr
== E_INVALIDARG
|| hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
2046 creation_desc
.BufferCount
= 1;
2047 creation_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
2049 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2051 /* Test swapchain creation with backbuffer width and height equal to 0. */
2052 expected_state
= initial_state
;
2053 expected_client_rect
= &expected_state
.fullscreen_state
.client_rect
;
2056 expected_width
= expected_client_rect
->right
;
2057 expected_height
= expected_client_rect
->bottom
;
2059 creation_desc
.BufferDesc
.Width
= 0;
2060 creation_desc
.BufferDesc
.Height
= 0;
2061 creation_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2062 creation_desc
.Windowed
= TRUE
;
2063 creation_desc
.Flags
= 0;
2064 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2065 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2066 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2067 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2068 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2069 result_desc
.BufferDesc
.Width
, expected_width
);
2070 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2071 result_desc
.BufferDesc
.Height
, expected_height
);
2072 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2073 IDXGISwapChain_Release(swapchain
);
2075 DestroyWindow(creation_desc
.OutputWindow
);
2076 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2077 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
2078 0, 0, 222, 222, 0, 0, 0, 0);
2079 expected_state
.fullscreen_state
.style
= WS_CLIPSIBLINGS
| WS_CAPTION
2080 | WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
;
2081 SetRect(&expected_state
.fullscreen_state
.window_rect
, 0, 0, 222, 222);
2082 GetClientRect(creation_desc
.OutputWindow
, expected_client_rect
);
2083 expected_width
= expected_client_rect
->right
;
2084 expected_height
= expected_client_rect
->bottom
;
2086 creation_desc
.BufferDesc
.Width
= 0;
2087 creation_desc
.BufferDesc
.Height
= 0;
2088 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2089 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2090 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2091 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2092 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2093 result_desc
.BufferDesc
.Width
, expected_width
);
2094 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2095 result_desc
.BufferDesc
.Height
, expected_height
);
2096 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2097 IDXGISwapChain_Release(swapchain
);
2099 DestroyWindow(creation_desc
.OutputWindow
);
2100 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2101 WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
2102 1, 1, 0, 0, 0, 0, 0, 0);
2103 expected_state
.fullscreen_state
.style
= WS_POPUP
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
2104 expected_state
.fullscreen_state
.exstyle
= 0;
2105 SetRect(&expected_state
.fullscreen_state
.window_rect
, 1, 1, 1, 1);
2106 SetRectEmpty(expected_client_rect
);
2107 expected_width
= expected_height
= 8;
2109 creation_desc
.BufferDesc
.Width
= 0;
2110 creation_desc
.BufferDesc
.Height
= 0;
2111 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2112 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2113 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2114 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2115 ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2116 result_desc
.BufferDesc
.Width
, expected_width
);
2117 ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2118 result_desc
.BufferDesc
.Height
, expected_height
);
2119 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2120 IDXGISwapChain_Release(swapchain
);
2122 DestroyWindow(creation_desc
.OutputWindow
);
2123 creation_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
2124 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2127 creation_desc
.Windowed
= FALSE
;
2128 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2129 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Got unexpected hr %#lx.\n", hr
);
2130 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2131 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2132 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2133 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2134 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2135 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2136 "Got unexpected hr %#lx.\n", hr
);
2137 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2138 IDXGISwapChain_Release(swapchain
);
2139 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2141 win_skip("GetContainingOutput() not supported.\n");
2144 if (result_desc
.Windowed
)
2146 win_skip("Fullscreen not supported.\n");
2147 IDXGIOutput_Release(expected_state
.target
);
2151 creation_desc
.BufferDesc
.Width
= 0;
2152 creation_desc
.BufferDesc
.Height
= 0;
2153 creation_desc
.Windowed
= FALSE
;
2154 creation_desc
.Flags
= 0;
2155 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2156 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2157 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2158 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2160 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2161 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2162 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2163 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2164 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2165 result_desc
.BufferDesc
.Width
, expected_width
);
2166 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2167 result_desc
.BufferDesc
.Height
, expected_height
);
2168 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2169 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2170 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2171 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2172 IDXGISwapChain_Release(swapchain
);
2174 /* Fullscreen and DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH */
2175 creation_desc
.BufferDesc
.Width
= 0;
2176 creation_desc
.BufferDesc
.Height
= 0;
2177 creation_desc
.Windowed
= FALSE
;
2178 creation_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2179 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2180 &creation_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 0, 0, expected_state
.target
);
2181 expected_width
= expected_client_rect
->right
- expected_client_rect
->left
;
2182 expected_height
= expected_client_rect
->bottom
- expected_client_rect
->top
;
2184 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &creation_desc
, &swapchain
);
2185 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2186 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
2187 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2188 todo_wine
ok(result_desc
.BufferDesc
.Width
== expected_width
, "Got width %u, expected %u.\n",
2189 result_desc
.BufferDesc
.Width
, expected_width
);
2190 todo_wine
ok(result_desc
.BufferDesc
.Height
== expected_height
, "Got height %u, expected %u.\n",
2191 result_desc
.BufferDesc
.Height
, expected_height
);
2192 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2193 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2194 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2195 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2196 IDXGISwapChain_Release(swapchain
);
2198 IDXGIOutput_Release(expected_state
.target
);
2201 IUnknown_Release(obj
);
2202 refcount
= IDXGIDevice_Release(device
);
2203 ok(!refcount
, "Device has %lu references left.\n", refcount
);
2204 refcount
= IDXGIAdapter_Release(adapter
);
2205 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
2206 refcount
= IDXGIFactory_Release(factory
);
2207 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
2208 check_window_fullscreen_state(creation_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2209 DestroyWindow(creation_desc
.OutputWindow
);
2212 static void test_get_containing_output(IUnknown
*device
, BOOL is_d3d12
)
2214 unsigned int adapter_idx
, output_idx
, output_count
;
2215 DXGI_OUTPUT_DESC output_desc
, output_desc2
;
2216 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2217 IDXGIOutput
*output
, *output2
;
2218 MONITORINFOEXW monitor_info
;
2219 IDXGISwapChain
*swapchain
;
2220 IDXGIFactory
*factory
;
2221 IDXGIAdapter
*adapter
;
2222 POINT points
[4 * 16];
2230 adapter
= get_adapter(device
, is_d3d12
);
2233 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
2238 while ((hr
= IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
)) != DXGI_ERROR_NOT_FOUND
)
2240 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2241 IDXGIOutput_Release(output
);
2244 IDXGIAdapter_Release(adapter
);
2246 swapchain_desc
.BufferDesc
.Width
= 100;
2247 swapchain_desc
.BufferDesc
.Height
= 100;
2248 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2249 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2250 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2251 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2252 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2253 swapchain_desc
.SampleDesc
.Count
= 1;
2254 swapchain_desc
.SampleDesc
.Quality
= 0;
2255 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2256 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2257 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test",
2258 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, 0, 0, 100, 100, 0, 0, 0, 0);
2259 swapchain_desc
.Windowed
= TRUE
;
2260 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2261 swapchain_desc
.Flags
= 0;
2263 get_factory(device
, is_d3d12
, &factory
);
2264 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2265 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2267 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, 0);
2268 ok(!!monitor
, "MonitorFromWindow failed.\n");
2270 monitor_info
.cbSize
= sizeof(monitor_info
);
2271 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2272 ok(ret
, "Failed to get monitor info.\n");
2274 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2275 ok(SUCCEEDED(hr
) || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2276 "Got unexpected hr %#lx.\n", hr
);
2277 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2279 win_skip("GetContainingOutput() not supported.\n");
2283 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2284 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2286 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2287 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2288 ok(output
!= output2
, "Got unexpected output pointers %p, %p.\n", output
, output2
);
2289 check_output_equal(output
, output2
);
2291 refcount
= IDXGIOutput_Release(output
);
2292 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
2293 refcount
= IDXGIOutput_Release(output2
);
2294 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
2296 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2297 "Got unexpected device name %s, expected %s.\n",
2298 wine_dbgstr_w(output_desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
2299 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2300 "Got unexpected desktop coordinates %s, expected %s.\n",
2301 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2302 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2304 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2307 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2310 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2311 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
,
2314 /* Move the OutputWindow to the current output. */
2315 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2316 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2317 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2319 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2322 win_skip("Adapter %u output %u: GetContainingOutput failed, hr %#lx.\n",
2323 adapter_idx
, output_idx
, hr
);
2324 IDXGIOutput_Release(output
);
2328 check_output_equal(output
, output2
);
2330 refcount
= IDXGIOutput_Release(output2
);
2331 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
2332 adapter_idx
, output_idx
, refcount
);
2334 /* Move the OutputWindow around the corners of the current output desktop coordinates. */
2335 for (i
= 0; i
< 4; ++i
)
2337 static const POINT offsets
[] =
2340 {-49, 0}, {-50, 0}, {-51, 0},
2341 { 0, -49}, { 0, -50}, { 0, -51},
2342 {-49, -49}, {-50, -49}, {-51, -49},
2343 {-49, -50}, {-50, -50}, {-51, -50},
2344 {-49, -51}, {-50, -51}, {-51, -51},
2346 unsigned int x
= 0, y
= 0;
2351 x
= output_desc
.DesktopCoordinates
.left
;
2352 y
= output_desc
.DesktopCoordinates
.top
;
2355 x
= output_desc
.DesktopCoordinates
.right
;
2356 y
= output_desc
.DesktopCoordinates
.top
;
2359 x
= output_desc
.DesktopCoordinates
.right
;
2360 y
= output_desc
.DesktopCoordinates
.bottom
;
2363 x
= output_desc
.DesktopCoordinates
.left
;
2364 y
= output_desc
.DesktopCoordinates
.bottom
;
2368 for (j
= 0; j
< ARRAY_SIZE(offsets
); ++j
)
2370 unsigned int idx
= ARRAY_SIZE(offsets
) * i
+ j
;
2371 assert(idx
< ARRAY_SIZE(points
));
2372 points
[idx
].x
= x
+ offsets
[j
].x
;
2373 points
[idx
].y
= y
+ offsets
[j
].y
;
2377 for (i
= 0; i
< ARRAY_SIZE(points
); ++i
)
2379 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, points
[i
].x
, points
[i
].y
,
2380 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2381 ok(ret
, "Adapter %u output %u point %u: Failed to set window position.\n",
2382 adapter_idx
, output_idx
, i
);
2384 monitor
= MonitorFromWindow(swapchain_desc
.OutputWindow
, MONITOR_DEFAULTTONEAREST
);
2385 ok(!!monitor
, "Adapter %u output %u point %u: Failed to get monitor from window.\n",
2386 adapter_idx
, output_idx
, i
);
2388 monitor_info
.cbSize
= sizeof(monitor_info
);
2389 ret
= GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
);
2390 ok(ret
, "Adapter %u output %u point %u: Failed to get monitor info.\n", adapter_idx
,
2393 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2394 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
),
2395 "Adapter %u output %u point %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, i
, hr
);
2398 ok(!!output2
, "Adapter %u output %u point %u: Got unexpected containing output %p.\n",
2399 adapter_idx
, output_idx
, i
, output2
);
2400 hr
= IDXGIOutput_GetDesc(output2
, &output_desc
);
2401 ok(hr
== S_OK
, "Adapter %u output %u point %u: Got unexpected hr %#lx.\n",
2402 adapter_idx
, output_idx
, i
, hr
);
2403 refcount
= IDXGIOutput_Release(output2
);
2404 ok(!refcount
, "Adapter %u output %u point %u: IDXGIOutput has %lu references left.\n",
2405 adapter_idx
, output_idx
, i
, refcount
);
2407 ok(!lstrcmpW(output_desc
.DeviceName
, monitor_info
.szDevice
),
2408 "Adapter %u output %u point %u: Got unexpected device name %s, expected %s.\n",
2409 adapter_idx
, output_idx
, i
, wine_dbgstr_w(output_desc
.DeviceName
),
2410 wine_dbgstr_w(monitor_info
.szDevice
));
2411 ok(EqualRect(&output_desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
2412 "Adapter %u output %u point %u: Expect desktop coordinates %s, got %s.\n",
2413 adapter_idx
, output_idx
, i
,
2414 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2415 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
2417 IDXGIOutput_Release(output
);
2419 IDXGIAdapter_Release(adapter
);
2422 /* Test GetContainingOutput with a full screen swapchain. The containing output should stay
2423 * the same even if the device window is moved */
2424 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2427 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
2431 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output2
);
2434 win_skip("GetContainingOutput failed, hr %#lx.\n", hr
);
2435 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2439 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2442 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2445 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2446 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2447 IDXGIOutput_Release(output
);
2449 /* Move the OutputWindow to the current output. */
2450 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
2451 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2452 ok(ret
, "Adapter %u output %u: SetWindowPos failed.\n", adapter_idx
, output_idx
);
2454 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2455 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n",
2456 adapter_idx
, output_idx
, hr
);
2457 ok(fullscreen
, "Adapter %u output %u: Expect swapchain full screen.\n", adapter_idx
,
2459 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2460 adapter_idx
, output_idx
, output2
, output
);
2461 IDXGIOutput_Release(output
);
2463 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2464 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2465 ok(output
== output2
, "Adapter %u output %u: Expect output %p, got %p.\n",
2466 adapter_idx
, output_idx
, output2
, output
);
2467 IDXGIOutput_Release(output
);
2469 IDXGIAdapter_Release(adapter
);
2472 IDXGIOutput_Release(output2
);
2473 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2474 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2476 /* Test GetContainingOutput after a full screen swapchain is made windowed by pressing
2477 * Alt+Enter, then move it to another output and use Alt+Enter to enter full screen */
2480 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2483 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
,
2484 output
? &output2
: &output
)); ++output_idx
)
2490 IDXGIAdapter_Release(adapter
);
2495 if (output
&& output2
)
2497 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2498 IDXGIOutput_Release(output
);
2501 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
2502 IDXGIOutput_Release(output2
);
2506 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to leave full screen on the first output */
2507 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2508 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2510 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2511 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2512 ok(!fullscreen
, "Expect swapchain not full screen.\n");
2514 /* Move the swapchain output window to the second output */
2515 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2516 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2517 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc2
.DesktopCoordinates
.left
,
2518 output_desc2
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2519 ok(ret
, "SetWindowPos failed.\n");
2521 /* Post an Alt + VK_RETURN WM_SYSKEYDOWN to enter full screen on the second output */
2522 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
2523 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
2526 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
2527 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2528 ok(fullscreen
, "Expect swapchain full screen.\n");
2529 ok(!!output
, "Expect output not NULL.\n");
2530 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2531 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2532 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2533 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2534 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2535 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2536 wine_dbgstr_w(output_desc
.DeviceName
));
2537 IDXGIOutput_Release(output
);
2540 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2541 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2542 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2543 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2544 hr
= IDXGIOutput_GetDesc(output2
, &output_desc2
);
2545 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2546 ok(!lstrcmpW(output_desc
.DeviceName
, output_desc2
.DeviceName
),
2547 "Expect device name %s, got %s.\n", wine_dbgstr_w(output_desc2
.DeviceName
),
2548 wine_dbgstr_w(output_desc
.DeviceName
));
2550 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2551 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2555 skip("This test requires two outputs.\n");
2559 IDXGIOutput_Release(output
);
2561 IDXGIOutput_Release(output2
);
2564 refcount
= IDXGISwapChain_Release(swapchain
);
2565 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2566 refcount
= IDXGIFactory_Release(factory
);
2567 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
2568 DestroyWindow(swapchain_desc
.OutputWindow
);
2571 static void test_swapchain_fullscreen_state(IDXGISwapChain
*swapchain
,
2572 IDXGIAdapter
*adapter
, const struct swapchain_fullscreen_state
*initial_state
)
2574 MONITORINFOEXW monitor_info
, *output_monitor_info
;
2575 struct swapchain_fullscreen_state expected_state
;
2576 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2577 DXGI_OUTPUT_DESC output_desc
;
2578 unsigned int i
, output_count
;
2579 IDXGIOutput
*output
;
2583 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
2584 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2586 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2588 expected_state
= *initial_state
;
2589 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2590 &swapchain_desc
, &initial_state
->fullscreen_state
.monitor_rect
, 800, 600, NULL
);
2591 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
2592 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2594 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2595 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2598 skip("Could not change fullscreen state.\n");
2599 IDXGIOutput_Release(expected_state
.target
);
2602 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2604 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2605 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2606 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2608 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2609 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2610 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2612 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2613 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2614 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2616 IDXGIOutput_Release(expected_state
.target
);
2617 expected_state
.target
= NULL
;
2620 while (IDXGIAdapter_EnumOutputs(adapter
, output_count
, &output
) != DXGI_ERROR_NOT_FOUND
)
2622 IDXGIOutput_Release(output
);
2626 output_monitor_info
= heap_calloc(output_count
, sizeof(*output_monitor_info
));
2627 ok(!!output_monitor_info
, "Failed to allocate memory.\n");
2628 for (i
= 0; i
< output_count
; ++i
)
2630 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2631 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2633 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2634 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2636 output_monitor_info
[i
].cbSize
= sizeof(*output_monitor_info
);
2637 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&output_monitor_info
[i
]);
2638 ok(ret
, "Failed to get monitor info.\n");
2640 IDXGIOutput_Release(output
);
2643 for (i
= 0; i
< output_count
; ++i
)
2645 RECT orig_monitor_rect
= output_monitor_info
[i
].rcMonitor
;
2646 IDXGIOutput
*target
;
2649 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2650 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2651 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2652 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2654 expected_state
= *initial_state
;
2655 expected_state
.target
= output
;
2656 expected_state
.fullscreen_state
.monitor
= output_desc
.Monitor
;
2657 expected_state
.fullscreen_state
.monitor_rect
= orig_monitor_rect
;
2658 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
2659 &swapchain_desc
, &orig_monitor_rect
, 800, 600, NULL
);
2661 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2662 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2663 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2666 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2667 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2668 ok(target
== output
, "Got target pointer %p, expected %p.\n", target
, output
);
2669 IDXGIOutput_Release(target
);
2671 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2672 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2673 ok(fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2675 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2676 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2677 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2678 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, output
);
2679 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
2680 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
2681 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2682 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2683 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2686 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2687 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2688 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2690 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2691 monitor_info
.cbSize
= sizeof(monitor_info
);
2692 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2693 ok(ret
, "Failed to get monitor info.\n");
2694 ok(EqualRect(&monitor_info
.rcMonitor
, &orig_monitor_rect
), "Got monitor rect %s, expected %s.\n",
2695 wine_dbgstr_rect(&monitor_info
.rcMonitor
), wine_dbgstr_rect(&orig_monitor_rect
));
2697 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
2698 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2700 IDXGIOutput_Release(output
);
2703 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2704 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2705 check_swapchain_fullscreen_state(swapchain
, initial_state
);
2707 for (i
= 0; i
< output_count
; ++i
)
2709 hr
= IDXGIAdapter_EnumOutputs(adapter
, i
, &output
);
2710 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2712 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2713 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2715 monitor_info
.cbSize
= sizeof(monitor_info
);
2716 ret
= GetMonitorInfoW(output_desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
2717 ok(ret
, "Failed to get monitor info.\n");
2719 ok(EqualRect(&monitor_info
.rcMonitor
, &output_monitor_info
[i
].rcMonitor
),
2720 "Got monitor rect %s, expected %s.\n",
2721 wine_dbgstr_rect(&monitor_info
.rcMonitor
),
2722 wine_dbgstr_rect(&output_monitor_info
[i
].rcMonitor
));
2724 IDXGIOutput_Release(output
);
2727 heap_free(output_monitor_info
);
2730 static void test_set_fullscreen(IUnknown
*device
, BOOL is_d3d12
)
2732 struct swapchain_fullscreen_state initial_state
;
2733 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2734 IDXGIAdapter
*adapter
= NULL
;
2735 IDXGISwapChain
*swapchain
;
2736 IDXGIFactory
*factory
;
2737 IDXGIOutput
*output
;
2742 get_factory(device
, is_d3d12
, &factory
);
2744 swapchain_desc
.BufferDesc
.Width
= 800;
2745 swapchain_desc
.BufferDesc
.Height
= 600;
2746 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2747 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2748 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2749 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2750 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2751 swapchain_desc
.SampleDesc
.Count
= 1;
2752 swapchain_desc
.SampleDesc
.Quality
= 0;
2753 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2754 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2755 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2756 swapchain_desc
.Windowed
= TRUE
;
2757 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2758 swapchain_desc
.Flags
= 0;
2760 memset(&initial_state
, 0, sizeof(initial_state
));
2761 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
2762 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2763 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2764 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
2765 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2766 "Got unexpected hr %#lx.\n", hr
);
2769 skip("Could not get output.\n");
2772 hr
= IDXGIOutput_GetParent(output
, &IID_IDXGIAdapter
, (void **)&adapter
);
2773 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2774 IDXGIOutput_Release(output
);
2776 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2777 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2778 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
2779 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
2780 "Got unexpected hr %#lx.\n", hr
);
2783 skip("Could not change fullscreen state.\n");
2786 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2787 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2788 refcount
= IDXGISwapChain_Release(swapchain
);
2789 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2791 DestroyWindow(swapchain_desc
.OutputWindow
);
2792 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2793 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2794 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2795 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2796 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2797 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2798 refcount
= IDXGISwapChain_Release(swapchain
);
2799 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2801 DestroyWindow(swapchain_desc
.OutputWindow
);
2802 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2803 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2804 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2805 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2806 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2807 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2808 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2809 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2810 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2811 DestroyWindow(swapchain_desc
.OutputWindow
);
2812 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2813 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2814 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2815 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2816 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2817 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2818 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2819 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2820 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2821 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2822 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2823 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2824 refcount
= IDXGISwapChain_Release(swapchain
);
2825 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2827 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2828 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2829 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2830 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2831 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2832 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2833 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2834 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2835 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2836 DestroyWindow(swapchain_desc
.OutputWindow
);
2837 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2838 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2839 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2840 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2841 ok(!!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2842 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2843 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2844 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2845 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2846 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2847 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2848 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
2849 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
2850 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2851 ok(!fullscreen
, "Got unexpected fullscreen %#x.\n", fullscreen
);
2852 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2853 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2854 refcount
= IDXGISwapChain_Release(swapchain
);
2855 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2857 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
2858 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2859 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
2860 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2861 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
2862 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
2863 test_swapchain_fullscreen_state(swapchain
, adapter
, &initial_state
);
2867 IDXGIAdapter_Release(adapter
);
2868 refcount
= IDXGISwapChain_Release(swapchain
);
2869 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
2870 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
2871 DestroyWindow(swapchain_desc
.OutputWindow
);
2873 refcount
= IDXGIFactory_Release(factory
);
2874 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
2877 static void test_default_fullscreen_target_output(IUnknown
*device
, BOOL is_d3d12
)
2879 IDXGIOutput
*output
, *containing_output
, *target
;
2880 unsigned int adapter_idx
, output_idx
;
2881 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
2882 DXGI_OUTPUT_DESC output_desc
;
2883 unsigned int width
, height
;
2884 IDXGISwapChain
*swapchain
;
2885 IDXGIFactory
*factory
;
2886 IDXGIAdapter
*adapter
;
2887 BOOL fullscreen
, ret
;
2892 get_factory(device
, is_d3d12
, &factory
);
2894 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
2895 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
2896 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
2897 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
2898 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
2899 swapchain_desc
.SampleDesc
.Count
= 1;
2900 swapchain_desc
.SampleDesc
.Quality
= 0;
2901 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
2902 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
2903 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
2904 swapchain_desc
.Flags
= 0;
2906 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
2909 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
2912 /* Windowed swapchain */
2913 swapchain_desc
.BufferDesc
.Width
= 640;
2914 swapchain_desc
.BufferDesc
.Height
= 480;
2915 swapchain_desc
.OutputWindow
= create_window();
2916 swapchain_desc
.Windowed
= TRUE
;
2917 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
2918 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2920 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
2921 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2922 ok(!fullscreen
, "Adapter %u output %u: Expected not fullscreen.\n", adapter_idx
, output_idx
);
2923 ok(!containing_output
, "Adapter %u output %u: Expected a null output.\n", adapter_idx
, output_idx
);
2925 /* Move the OutputWindow to the current output. */
2926 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
2927 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2928 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0,
2929 output_desc
.DesktopCoordinates
.left
, output_desc
.DesktopCoordinates
.top
,
2930 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
2931 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#lx.\n", adapter_idx
,
2932 output_idx
, GetLastError());
2934 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2935 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
2936 "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2937 if (hr
== DXGI_ERROR_UNSUPPORTED
)
2939 win_skip("Adapter %u output %u: GetContainingOutput() not supported.\n",
2940 adapter_idx
, output_idx
);
2941 IDXGISwapChain_Release(swapchain
);
2942 IDXGIOutput_Release(output
);
2943 DestroyWindow(swapchain_desc
.OutputWindow
);
2947 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
2948 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
2949 "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2950 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
2952 skip("Adapter %u output %u: Could not change fullscreen state.\n", adapter_idx
,
2954 IDXGIOutput_Release(containing_output
);
2955 IDXGISwapChain_Release(swapchain
);
2956 IDXGIOutput_Release(output
);
2957 DestroyWindow(swapchain_desc
.OutputWindow
);
2960 GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
2961 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
2962 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
2963 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
2964 wine_dbgstr_rect(&window_rect
));
2967 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
2968 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2969 ok(target
!= containing_output
,
2970 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
2971 output_idx
, target
, containing_output
);
2972 check_output_equal(target
, containing_output
);
2974 refcount
= IDXGIOutput_Release(containing_output
);
2975 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
2976 adapter_idx
, output_idx
, refcount
);
2978 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
2979 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2980 ok(containing_output
== target
,
2981 "Adapter %u output %u: Got unexpected containing output %p, expected %p.\n",
2982 adapter_idx
, output_idx
, containing_output
, target
);
2983 refcount
= IDXGIOutput_Release(containing_output
);
2984 ok(refcount
>= 2, "Adapter %u output %u: Got unexpected refcount %lu.\n", adapter_idx
,
2985 output_idx
, refcount
);
2986 refcount
= IDXGIOutput_Release(target
);
2987 ok(refcount
>= 1, "Adapter %u output %u: Got unexpected refcount %lu.\n", adapter_idx
,
2988 output_idx
, refcount
);
2990 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
2991 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
2992 refcount
= IDXGISwapChain_Release(swapchain
);
2993 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %lu references left.\n",
2994 adapter_idx
, output_idx
, refcount
);
2995 DestroyWindow(swapchain_desc
.OutputWindow
);
2997 /* Full screen swapchain */
2998 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
2999 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
3000 swapchain_desc
.BufferDesc
.Width
= width
;
3001 swapchain_desc
.BufferDesc
.Height
= height
;
3002 swapchain_desc
.OutputWindow
= create_window();
3003 swapchain_desc
.Windowed
= FALSE
;
3004 ret
= SetWindowPos(swapchain_desc
.OutputWindow
, 0, output_desc
.DesktopCoordinates
.left
,
3005 output_desc
.DesktopCoordinates
.top
, 0, 0, SWP_NOSIZE
| SWP_NOZORDER
);
3006 ok(ret
, "Adapter %u output %u: SetWindowPos failed, error %#lx.\n", adapter_idx
,
3007 output_idx
, GetLastError());
3008 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3011 skip("Adapter %u output %u: CreateSwapChain failed, hr %#lx.\n", adapter_idx
,
3013 IDXGIOutput_Release(output
);
3014 DestroyWindow(swapchain_desc
.OutputWindow
);
3018 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &containing_output
);
3019 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3020 ok(fullscreen
, "Adapter %u output %u: Expected fullscreen.\n", adapter_idx
, output_idx
);
3021 ok(!!containing_output
, "Adapter %u output %u: Expected a valid output.\n", adapter_idx
, output_idx
);
3022 if (containing_output
)
3023 IDXGIOutput_Release(containing_output
);
3025 ret
= GetWindowRect(swapchain_desc
.OutputWindow
, &window_rect
);
3026 ok(ret
, "Adapter %u output %u: GetWindowRect failed, error %#lx.\n", adapter_idx
,
3027 output_idx
, GetLastError());
3028 ok(EqualRect(&window_rect
, &output_desc
.DesktopCoordinates
),
3029 "Adapter %u output %u: Expect window rect %s, got %s.\n", adapter_idx
,
3030 output_idx
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3031 wine_dbgstr_rect(&window_rect
));
3033 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &containing_output
);
3034 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3035 ok(containing_output
!= output
,
3036 "Adapter %u output %u: Got unexpected output %p, expected %p.\n", adapter_idx
,
3037 output_idx
, output
, containing_output
);
3038 check_output_equal(output
, containing_output
);
3039 IDXGIOutput_Release(containing_output
);
3041 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3042 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3043 refcount
= IDXGISwapChain_Release(swapchain
);
3044 ok(!refcount
, "Adapter %u output %u: IDXGISwapChain has %lu references left.\n",
3045 adapter_idx
, output_idx
, refcount
);
3046 refcount
= IDXGIOutput_Release(output
);
3047 ok(!refcount
, "Adapter %u output %u: IDXGIOutput has %lu references left.\n",
3048 adapter_idx
, output_idx
, refcount
);
3049 DestroyWindow(swapchain_desc
.OutputWindow
);
3051 IDXGIAdapter_Release(adapter
);
3054 refcount
= IDXGIFactory_Release(factory
);
3055 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
3058 static void test_windowed_resize_target(IDXGISwapChain
*swapchain
, HWND window
,
3059 struct swapchain_fullscreen_state
*state
)
3061 struct swapchain_fullscreen_state expected_state
;
3062 struct fullscreen_state
*e
;
3063 DXGI_MODE_DESC mode
;
3071 unsigned int width
, height
;
3084 check_swapchain_fullscreen_state(swapchain
, state
);
3085 expected_state
= *state
;
3086 e
= &expected_state
.fullscreen_state
;
3088 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3090 SetRect(&e
->client_rect
, 0, 0, sizes
[i
].width
, sizes
[i
].height
);
3091 e
->window_rect
= e
->client_rect
;
3092 ret
= AdjustWindowRectEx(&e
->window_rect
, GetWindowLongW(window
, GWL_STYLE
),
3093 FALSE
, GetWindowLongW(window
, GWL_EXSTYLE
));
3094 ok(ret
, "AdjustWindowRectEx failed.\n");
3095 if (GetMenu(window
))
3096 e
->client_rect
.bottom
-= GetSystemMetrics(SM_CYMENU
);
3097 SetRect(&e
->window_rect
, 0, 0,
3098 e
->window_rect
.right
- e
->window_rect
.left
,
3099 e
->window_rect
.bottom
- e
->window_rect
.top
);
3100 GetWindowRect(window
, &window_rect
);
3101 OffsetRect(&e
->window_rect
, window_rect
.left
, window_rect
.top
);
3102 if (e
->window_rect
.right
>= e
->monitor_rect
.right
3103 || e
->window_rect
.bottom
>= e
->monitor_rect
.bottom
)
3105 skip("Test %u: Window %s does not fit on screen %s.\n",
3106 i
, wine_dbgstr_rect(&e
->window_rect
), wine_dbgstr_rect(&e
->monitor_rect
));
3110 memset(&mode
, 0, sizeof(mode
));
3111 mode
.Width
= sizes
[i
].width
;
3112 mode
.Height
= sizes
[i
].height
;
3113 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3114 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3115 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3118 ret
= SetWindowPos(window
, 0, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOZORDER
);
3119 ok(ret
, "SetWindowPos failed, error %#lx.\n", GetLastError());
3120 GetWindowRect(window
, &e
->window_rect
);
3121 GetClientRect(window
, &e
->client_rect
);
3122 ret
= SetWindowPos(window
, 0, 0, 0, 200, 200, SWP_NOMOVE
| SWP_NOZORDER
);
3123 ok(ret
, "SetWindowPos failed, error %#lx.\n", GetLastError());
3125 memset(&mode
, 0, sizeof(mode
));
3126 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3127 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3128 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3130 GetWindowRect(window
, &e
->window_rect
);
3131 GetClientRect(window
, &e
->client_rect
);
3132 *state
= expected_state
;
3135 static void test_fullscreen_resize_target(IDXGISwapChain
*swapchain
,
3136 const struct swapchain_fullscreen_state
*initial_state
)
3138 struct swapchain_fullscreen_state expected_state
;
3139 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3140 DXGI_OUTPUT_DESC output_desc
;
3141 unsigned int i
, mode_count
;
3142 DXGI_MODE_DESC
*modes
;
3143 IDXGIOutput
*target
;
3146 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3147 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3149 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, NULL
, &target
);
3150 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3152 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
3153 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 testbot */
3154 "Got unexpected hr %#lx.\n", hr
);
3155 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3157 win_skip("GetDisplayModeList() not supported.\n");
3158 IDXGIOutput_Release(target
);
3162 modes
= heap_calloc(mode_count
, sizeof(*modes
));
3163 ok(!!modes
, "Failed to allocate memory.\n");
3165 hr
= IDXGIOutput_GetDisplayModeList(target
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
3166 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3168 expected_state
= *initial_state
;
3169 for (i
= 0; i
< min(mode_count
, 20); ++i
)
3171 /* FIXME: Modes with scaling aren't fully tested. */
3172 if (!(swapchain_desc
.Flags
& DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
)
3173 && modes
[i
].Scaling
!= DXGI_MODE_SCALING_UNSPECIFIED
)
3176 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3177 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3179 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3180 &swapchain_desc
, &output_desc
.DesktopCoordinates
, modes
[i
].Width
, modes
[i
].Height
, NULL
);
3182 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &modes
[i
]);
3183 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, "Got unexpected hr %#lx.\n", hr
);
3184 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3186 skip("Failed to change to video mode %u.\n", i
);
3189 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3191 hr
= IDXGIOutput_GetDesc(target
, &output_desc
);
3192 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3193 ok(EqualRect(&output_desc
.DesktopCoordinates
, &expected_state
.fullscreen_state
.monitor_rect
),
3194 "Got desktop coordinates %s, expected %s.\n",
3195 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
),
3196 wine_dbgstr_rect(&expected_state
.fullscreen_state
.monitor_rect
));
3200 IDXGIOutput_Release(target
);
3203 static void test_resize_target(IUnknown
*device
, BOOL is_d3d12
)
3205 struct swapchain_fullscreen_state initial_state
, expected_state
;
3206 unsigned int adapter_idx
, output_idx
, test_idx
;
3207 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3208 DXGI_OUTPUT_DESC output_desc
;
3209 IDXGISwapChain
*swapchain
;
3210 IDXGIFactory
*factory
;
3211 IDXGIAdapter
*adapter
;
3212 IDXGIOutput
*output
;
3225 {{ 0, 0}, TRUE
, FALSE
, 0},
3226 {{10, 10}, TRUE
, FALSE
, 0},
3227 {{ 0, 0}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3228 {{10, 10}, TRUE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3229 {{ 0, 0}, FALSE
, FALSE
, 0},
3230 {{ 0, 0}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3231 {{10, 10}, FALSE
, FALSE
, 0},
3232 {{10, 10}, FALSE
, FALSE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3233 {{ 0, 0}, FALSE
, TRUE
, 0},
3234 {{ 0, 0}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3235 {{10, 10}, FALSE
, TRUE
, 0},
3236 {{10, 10}, FALSE
, TRUE
, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
},
3239 get_factory(device
, is_d3d12
, &factory
);
3241 swapchain_desc
.BufferDesc
.Width
= 800;
3242 swapchain_desc
.BufferDesc
.Height
= 600;
3243 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3244 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3245 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3246 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3247 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3248 swapchain_desc
.SampleDesc
.Count
= 1;
3249 swapchain_desc
.SampleDesc
.Quality
= 0;
3250 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3251 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
3252 swapchain_desc
.Windowed
= TRUE
;
3253 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
3254 swapchain_desc
.Flags
= 0;
3256 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
3259 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
3262 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
3263 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
3265 for (test_idx
= 0; test_idx
< ARRAY_SIZE(tests
); ++test_idx
)
3267 swapchain_desc
.Flags
= tests
[test_idx
].flags
;
3268 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0,
3269 output_desc
.DesktopCoordinates
.left
+ tests
[test_idx
].origin
.x
,
3270 output_desc
.DesktopCoordinates
.top
+ tests
[test_idx
].origin
.y
,
3271 400, 200, 0, 0, 0, 0);
3272 if (tests
[test_idx
].menu
)
3274 HMENU menu_bar
= CreateMenu();
3275 HMENU menu
= CreateMenu();
3276 AppendMenuA(menu_bar
, MF_POPUP
, (UINT_PTR
)menu
, "Menu");
3277 SetMenu(swapchain_desc
.OutputWindow
, menu_bar
);
3280 memset(&initial_state
, 0, sizeof(initial_state
));
3281 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3283 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
3284 ok(hr
== S_OK
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3285 adapter_idx
, output_idx
, test_idx
, hr
);
3286 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3288 expected_state
= initial_state
;
3289 if (tests
[test_idx
].fullscreen
)
3291 expected_state
.fullscreen
= TRUE
;
3292 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3293 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
, 800, 600, NULL
);
3294 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &expected_state
.target
);
3295 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3296 "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3297 adapter_idx
, output_idx
, test_idx
, hr
);
3298 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3300 win_skip("Adapter %u output %u test %u: GetContainingOutput() not supported.\n",
3301 adapter_idx
, output_idx
, test_idx
);
3302 IDXGISwapChain_Release(swapchain
);
3303 DestroyWindow(swapchain_desc
.OutputWindow
);
3307 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
3308 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
,
3309 "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3310 adapter_idx
, output_idx
, test_idx
, hr
);
3311 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
3313 skip("Adapter %u output %u test %u: Could not change fullscreen state.\n",
3314 adapter_idx
, output_idx
, test_idx
);
3315 IDXGIOutput_Release(expected_state
.target
);
3316 IDXGISwapChain_Release(swapchain
);
3317 DestroyWindow(swapchain_desc
.OutputWindow
);
3321 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3323 hr
= IDXGISwapChain_ResizeTarget(swapchain
, NULL
);
3324 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3325 adapter_idx
, output_idx
, test_idx
, hr
);
3326 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3328 if (tests
[test_idx
].fullscreen
)
3330 test_fullscreen_resize_target(swapchain
, &expected_state
);
3332 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3333 ok(hr
== S_OK
, "Adapter %u output %u test %u: Got unexpected hr %#lx.\n",
3334 adapter_idx
, output_idx
, test_idx
, hr
);
3335 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3336 IDXGIOutput_Release(expected_state
.target
);
3337 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3338 expected_state
= initial_state
;
3342 test_windowed_resize_target(swapchain
, swapchain_desc
.OutputWindow
, &expected_state
);
3344 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3347 refcount
= IDXGISwapChain_Release(swapchain
);
3348 ok(!refcount
, "Adapter %u output %u test %u: IDXGISwapChain has %lu references left.\n",
3349 adapter_idx
, output_idx
, test_idx
, refcount
);
3350 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &expected_state
.fullscreen_state
);
3351 DestroyWindow(swapchain_desc
.OutputWindow
);
3353 IDXGIOutput_Release(output
);
3355 IDXGIAdapter_Release(adapter
);
3357 refcount
= IDXGIFactory_Release(factory
);
3358 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
3361 static LRESULT CALLBACK
resize_target_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
3363 IDXGISwapChain
*swapchain
= (IDXGISwapChain
*)GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
3364 DXGI_SWAP_CHAIN_DESC desc
;
3370 ok(!!swapchain
, "GWLP_USERDATA is NULL.\n");
3371 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
3372 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3373 ok(desc
.BufferDesc
.Width
== 800, "Got unexpected buffer width %u.\n", desc
.BufferDesc
.Width
);
3374 ok(desc
.BufferDesc
.Height
== 600, "Got unexpected buffer height %u.\n", desc
.BufferDesc
.Height
);
3378 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
3382 struct window_thread_data
3385 HANDLE window_created
;
3389 static DWORD WINAPI
window_thread(void *data
)
3391 struct window_thread_data
*thread_data
= data
;
3396 memset(&wc
, 0, sizeof(wc
));
3397 wc
.lpfnWndProc
= resize_target_wndproc
;
3398 wc
.lpszClassName
= "dxgi_resize_target_wndproc_wc";
3399 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
3401 thread_data
->window
= CreateWindowA("dxgi_resize_target_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3402 ok(!!thread_data
->window
, "Failed to create window.\n");
3404 ret
= SetEvent(thread_data
->window_created
);
3405 ok(ret
, "Failed to set event, last error %#lx.\n", GetLastError());
3409 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3410 DispatchMessageA(&msg
);
3412 ret
= WaitForSingleObject(thread_data
->finished
, 0);
3413 if (ret
!= WAIT_TIMEOUT
)
3416 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for event, ret %#x, last error %#lx.\n", ret
, GetLastError());
3418 DestroyWindow(thread_data
->window
);
3419 thread_data
->window
= NULL
;
3421 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
3426 static void test_resize_target_wndproc(void)
3428 struct window_thread_data thread_data
;
3429 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
3430 IDXGISwapChain
*swapchain
;
3431 IDXGIFactory
*factory
;
3432 IDXGIAdapter
*adapter
;
3433 DXGI_MODE_DESC mode
;
3434 IDXGIDevice
*device
;
3442 if (!(device
= create_device(0)))
3444 skip("Failed to create device.\n");
3448 memset(&thread_data
, 0, sizeof(thread_data
));
3449 thread_data
.window_created
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3450 ok(!!thread_data
.window_created
, "Failed to create event, last error %#lx.\n", GetLastError());
3451 thread_data
.finished
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3452 ok(!!thread_data
.finished
, "Failed to create event, last error %#lx.\n", GetLastError());
3454 thread
= CreateThread(NULL
, 0, window_thread
, &thread_data
, 0, NULL
);
3455 ok(!!thread
, "Failed to create thread, last error %#lx.\n", GetLastError());
3456 ret
= WaitForSingleObject(thread_data
.window_created
, INFINITE
);
3457 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#lx.\n", ret
, GetLastError());
3459 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3460 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3461 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3462 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3464 swapchain_desc
.BufferDesc
.Width
= 800;
3465 swapchain_desc
.BufferDesc
.Height
= 600;
3466 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3467 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3468 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3469 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3470 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3471 swapchain_desc
.SampleDesc
.Count
= 1;
3472 swapchain_desc
.SampleDesc
.Quality
= 0;
3473 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3474 swapchain_desc
.BufferCount
= 1;
3475 swapchain_desc
.OutputWindow
= thread_data
.window
;
3476 swapchain_desc
.Windowed
= TRUE
;
3477 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3478 swapchain_desc
.Flags
= 0;
3479 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3480 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3482 data
= SetWindowLongPtrA(thread_data
.window
, GWLP_USERDATA
, (LONG_PTR
)swapchain
);
3483 ok(!data
, "Got unexpected GWLP_USERDATA %p.\n", (void *)data
);
3485 memset(&mode
, 0, sizeof(mode
));
3488 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode
);
3489 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3491 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
3492 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3493 ok(swapchain_desc
.BufferDesc
.Width
== 800,
3494 "Got unexpected buffer width %u.\n", swapchain_desc
.BufferDesc
.Width
);
3495 ok(swapchain_desc
.BufferDesc
.Height
== 600,
3496 "Got unexpected buffer height %u.\n", swapchain_desc
.BufferDesc
.Height
);
3498 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
3499 ok(ret
, "Failed to get client rect.\n");
3500 ok(rect
.right
== mode
.Width
&& rect
.bottom
== mode
.Height
,
3501 "Got unexpected client rect %s.\n", wine_dbgstr_rect(&rect
));
3503 refcount
= IDXGISwapChain_Release(swapchain
);
3504 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3506 IDXGIAdapter_Release(adapter
);
3507 refcount
= IDXGIDevice_Release(device
);
3508 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3509 refcount
= IDXGIFactory_Release(factory
);
3510 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3512 ret
= SetEvent(thread_data
.finished
);
3513 ok(ret
, "Failed to set event, last error %#lx.\n", GetLastError());
3514 ret
= WaitForSingleObject(thread
, INFINITE
);
3515 ok(ret
== WAIT_OBJECT_0
, "Failed to wait for thread, ret %#x, last error %#lx.\n", ret
, GetLastError());
3516 CloseHandle(thread
);
3517 CloseHandle(thread_data
.window_created
);
3518 CloseHandle(thread_data
.finished
);
3521 static void test_inexact_modes(void)
3523 struct swapchain_fullscreen_state initial_state
, expected_state
;
3524 DXGI_SWAP_CHAIN_DESC swapchain_desc
, result_desc
;
3525 IDXGIOutput
*output
= NULL
;
3526 IDXGISwapChain
*swapchain
;
3527 IDXGIFactory
*factory
;
3528 IDXGIAdapter
*adapter
;
3529 IDXGIDevice
*device
;
3536 unsigned int width
, height
;
3545 if (!(device
= create_device(0)))
3547 skip("Failed to create device.\n");
3551 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
3552 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3554 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
3555 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3557 swapchain_desc
.BufferDesc
.Width
= 800;
3558 swapchain_desc
.BufferDesc
.Height
= 600;
3559 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
3560 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
3561 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
3562 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
3563 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
3564 swapchain_desc
.SampleDesc
.Count
= 1;
3565 swapchain_desc
.SampleDesc
.Quality
= 0;
3566 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
3567 swapchain_desc
.BufferCount
= 1;
3568 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
3569 swapchain_desc
.Windowed
= FALSE
;
3570 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
3571 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
3573 memset(&initial_state
, 0, sizeof(initial_state
));
3574 capture_fullscreen_state(&initial_state
.fullscreen_state
, swapchain_desc
.OutputWindow
);
3576 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3577 ok(hr
== S_OK
|| hr
== DXGI_STATUS_OCCLUDED
, "Got unexpected hr %#lx.\n", hr
);
3578 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3579 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3580 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3581 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3582 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
3583 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Win 7 testbot */,
3584 "Got unexpected hr %#lx.\n", hr
);
3585 refcount
= IDXGISwapChain_Release(swapchain
);
3586 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3587 if (hr
== DXGI_ERROR_UNSUPPORTED
)
3589 win_skip("GetContainingOutput() not supported.\n");
3592 if (result_desc
.Windowed
)
3594 win_skip("Fullscreen not supported.\n");
3598 check_window_fullscreen_state(swapchain_desc
.OutputWindow
, &initial_state
.fullscreen_state
);
3600 for (i
= 0; i
< ARRAY_SIZE(sizes
); ++i
)
3602 /* Test CreateSwapChain(). */
3603 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3604 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3605 swapchain_desc
.Windowed
= FALSE
;
3607 expected_state
= initial_state
;
3608 compute_expected_swapchain_fullscreen_state_after_fullscreen_change(&expected_state
,
3609 &swapchain_desc
, &initial_state
.fullscreen_state
.monitor_rect
,
3610 sizes
[i
].width
, sizes
[i
].height
, output
);
3612 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3613 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3615 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3616 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3617 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3618 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3619 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3620 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3621 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3623 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3624 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3625 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3627 refcount
= IDXGISwapChain_Release(swapchain
);
3628 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3630 /* Test SetFullscreenState(). */
3631 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3632 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3633 swapchain_desc
.Windowed
= TRUE
;
3635 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3636 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3638 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3639 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3641 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3642 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3643 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3644 ok(result_desc
.BufferDesc
.Width
== sizes
[i
].width
, "Got width %u, expected %u.\n",
3645 result_desc
.BufferDesc
.Width
, sizes
[i
].width
);
3646 ok(result_desc
.BufferDesc
.Height
== sizes
[i
].height
, "Got height %u, expected %u.\n",
3647 result_desc
.BufferDesc
.Height
, sizes
[i
].height
);
3649 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3650 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3651 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3653 refcount
= IDXGISwapChain_Release(swapchain
);
3654 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3656 /* Test ResizeTarget(). */
3657 swapchain_desc
.BufferDesc
.Width
= 800;
3658 swapchain_desc
.BufferDesc
.Height
= 600;
3659 swapchain_desc
.Windowed
= TRUE
;
3661 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
3662 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3664 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
3665 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3667 swapchain_desc
.BufferDesc
.Width
= sizes
[i
].width
;
3668 swapchain_desc
.BufferDesc
.Height
= sizes
[i
].height
;
3669 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &swapchain_desc
.BufferDesc
);
3670 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3672 check_swapchain_fullscreen_state(swapchain
, &expected_state
);
3673 hr
= IDXGISwapChain_GetDesc(swapchain
, &result_desc
);
3674 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3675 ok(result_desc
.BufferDesc
.Width
== 800, "Got width %u.\n", result_desc
.BufferDesc
.Width
);
3676 ok(result_desc
.BufferDesc
.Height
== 600, "Got height %u.\n", result_desc
.BufferDesc
.Height
);
3678 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
3679 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3680 check_swapchain_fullscreen_state(swapchain
, &initial_state
);
3682 refcount
= IDXGISwapChain_Release(swapchain
);
3683 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
3688 IDXGIOutput_Release(output
);
3689 IDXGIAdapter_Release(adapter
);
3690 refcount
= IDXGIDevice_Release(device
);
3691 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3692 refcount
= IDXGIFactory_Release(factory
);
3693 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3694 DestroyWindow(swapchain_desc
.OutputWindow
);
3697 static void test_create_factory(void)
3703 iface
= (void *)0xdeadbeef;
3704 hr
= CreateDXGIFactory(&IID_IDXGIDevice
, (void **)&iface
);
3705 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3706 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3708 hr
= CreateDXGIFactory(&IID_IUnknown
, (void **)&iface
);
3709 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3710 IUnknown_Release(iface
);
3712 hr
= CreateDXGIFactory(&IID_IDXGIObject
, (void **)&iface
);
3713 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3714 IUnknown_Release(iface
);
3716 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&iface
);
3717 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3718 check_interface(iface
, &IID_IDXGIFactory1
, FALSE
, FALSE
);
3719 IUnknown_Release(iface
);
3721 iface
= (void *)0xdeadbeef;
3722 hr
= CreateDXGIFactory(&IID_IDXGIFactory1
, (void **)&iface
);
3723 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3724 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3727 hr
= CreateDXGIFactory(&IID_IDXGIFactory2
, (void **)&iface
);
3728 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3729 "Got unexpected hr %#lx.\n", hr
);
3732 refcount
= IUnknown_Release(iface
);
3733 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3736 if (!pCreateDXGIFactory1
)
3738 win_skip("CreateDXGIFactory1 not available.\n");
3742 iface
= (void *)0xdeadbeef;
3743 hr
= pCreateDXGIFactory1(&IID_IDXGIDevice
, (void **)&iface
);
3744 ok(hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
3745 ok(!iface
, "Got unexpected iface %p.\n", iface
);
3747 hr
= pCreateDXGIFactory1(&IID_IUnknown
, (void **)&iface
);
3748 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3749 IUnknown_Release(iface
);
3751 hr
= pCreateDXGIFactory1(&IID_IDXGIObject
, (void **)&iface
);
3752 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3753 IUnknown_Release(iface
);
3755 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory
, (void **)&iface
);
3756 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3757 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3758 refcount
= IUnknown_Release(iface
);
3759 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3761 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory1
, (void **)&iface
);
3762 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3763 IUnknown_Release(iface
);
3766 hr
= pCreateDXGIFactory1(&IID_IDXGIFactory2
, (void **)&iface
);
3767 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Not available on all Windows versions. */,
3768 "Got unexpected hr %#lx.\n", hr
);
3771 refcount
= IUnknown_Release(iface
);
3772 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3775 if (!pCreateDXGIFactory2
)
3777 win_skip("CreateDXGIFactory2 not available.\n");
3781 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory3
, (void **)&iface
);
3782 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3783 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3784 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3785 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3786 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3787 /* Not available on all Windows versions. */
3788 check_interface(iface
, &IID_IDXGIFactory4
, TRUE
, TRUE
);
3789 check_interface(iface
, &IID_IDXGIFactory5
, TRUE
, TRUE
);
3790 refcount
= IUnknown_Release(iface
);
3791 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3793 hr
= pCreateDXGIFactory2(0, &IID_IDXGIFactory
, (void **)&iface
);
3794 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3795 check_interface(iface
, &IID_IDXGIFactory
, TRUE
, FALSE
);
3796 check_interface(iface
, &IID_IDXGIFactory1
, TRUE
, FALSE
);
3797 check_interface(iface
, &IID_IDXGIFactory2
, TRUE
, FALSE
);
3798 check_interface(iface
, &IID_IDXGIFactory3
, TRUE
, FALSE
);
3799 refcount
= IUnknown_Release(iface
);
3800 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
3803 static void test_private_data(void)
3805 ULONG refcount
, expected_refcount
;
3806 IDXGIDevice
*device
;
3808 IDXGIDevice
*test_object
;
3810 static const DWORD data
[] = {1, 2, 3, 4};
3812 static const GUID dxgi_private_data_test_guid
=
3817 {0xa3, 0x7f, 0x9b, 0x1d, 0xf4, 0x88, 0xc5, 0xfc}
3819 static const GUID dxgi_private_data_test_guid2
=
3824 {0x9b, 0x4b, 0x89, 0xd7, 0xd1, 0x12, 0xe7, 0x2b}
3827 if (!(device
= create_device(0)))
3829 skip("Failed to create device.\n");
3833 test_object
= create_device(0);
3835 /* SetPrivateData with a pointer of NULL has the purpose of FreePrivateData in previous
3836 * d3d versions. A successful clear returns S_OK. A redundant clear S_FALSE. Setting a
3837 * NULL interface is not considered a clear but as setting an interface pointer that
3838 * happens to be NULL. */
3839 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 0, NULL
);
3840 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3841 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3842 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3843 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3844 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3845 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, ~0U, NULL
);
3846 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3848 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3849 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3850 size
= sizeof(ptr
) * 2;
3851 ptr
= (IUnknown
*)0xdeadbeef;
3852 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3853 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3854 ok(!ptr
, "Got unexpected pointer %p.\n", ptr
);
3855 ok(size
== sizeof(IUnknown
*), "Got unexpected size %u.\n", size
);
3857 refcount
= get_refcount(test_object
);
3858 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3859 (IUnknown
*)test_object
);
3860 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3861 expected_refcount
= refcount
+ 1;
3862 refcount
= get_refcount(test_object
);
3863 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3864 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3865 (IUnknown
*)test_object
);
3866 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3867 refcount
= get_refcount(test_object
);
3868 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3870 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
, NULL
);
3871 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3872 expected_refcount
--;
3873 refcount
= get_refcount(test_object
);
3874 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3876 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3877 (IUnknown
*)test_object
);
3878 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3879 size
= sizeof(data
);
3880 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, size
, data
);
3881 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3882 refcount
= get_refcount(test_object
);
3883 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3884 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3885 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3886 hr
= IDXGIDevice_SetPrivateData(device
, &dxgi_private_data_test_guid
, 42, NULL
);
3887 ok(hr
== S_FALSE
, "Got unexpected hr %#lx.\n", hr
);
3889 hr
= IDXGIDevice_SetPrivateDataInterface(device
, &dxgi_private_data_test_guid
,
3890 (IUnknown
*)test_object
);
3891 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3892 expected_refcount
++;
3893 size
= 2 * sizeof(ptr
);
3895 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3896 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3897 ok(size
== sizeof(test_object
), "Got unexpected size %u.\n", size
);
3898 expected_refcount
++;
3899 refcount
= get_refcount(test_object
);
3900 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3902 IUnknown_Release(ptr
);
3903 expected_refcount
--;
3905 ptr
= (IUnknown
*)0xdeadbeef;
3907 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3908 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3909 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3910 size
= 2 * sizeof(ptr
);
3911 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, NULL
);
3912 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
3913 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3914 refcount
= get_refcount(test_object
);
3915 ok(refcount
== expected_refcount
, "Got unexpected refcount %lu, expected %lu.\n", refcount
, expected_refcount
);
3918 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, &size
, &ptr
);
3919 ok(hr
== DXGI_ERROR_MORE_DATA
, "Got unexpected hr %#lx.\n", hr
);
3920 ok(size
== sizeof(device
), "Got unexpected size %u.\n", size
);
3921 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3922 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, NULL
, NULL
);
3923 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
3925 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid2
, &size
, &ptr
);
3926 ok(hr
== DXGI_ERROR_NOT_FOUND
, "Got unexpected hr %#lx.\n", hr
);
3927 ok(size
== 0, "Got unexpected size %u.\n", size
);
3928 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3929 hr
= IDXGIDevice_GetPrivateData(device
, &dxgi_private_data_test_guid
, NULL
, &ptr
);
3930 ok(hr
== E_INVALIDARG
, "Got unexpected hr %#lx.\n", hr
);
3931 ok(ptr
== (IUnknown
*)0xdeadbeef, "Got unexpected pointer %p.\n", ptr
);
3933 refcount
= IDXGIDevice_Release(device
);
3934 ok(!refcount
, "Device has %lu references left.\n", refcount
);
3935 refcount
= IDXGIDevice_Release(test_object
);
3936 ok(!refcount
, "Test object has %lu references left.\n", refcount
);
3939 #define check_surface_desc(a, b) check_surface_desc_(__LINE__, a, b)
3940 static void check_surface_desc_(unsigned int line
, IDXGISurface
*surface
,
3941 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3943 DXGI_SURFACE_DESC surface_desc
;
3946 hr
= IDXGISurface_GetDesc(surface
, &surface_desc
);
3947 ok_(__FILE__
, line
)(hr
== S_OK
, "Failed to get surface desc, hr %#lx.\n", hr
);
3948 ok_(__FILE__
, line
)(surface_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3949 "Got Width %u, expected %u.\n", surface_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3950 ok_(__FILE__
, line
)(surface_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3951 "Got Height %u, expected %u.\n", surface_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3952 ok_(__FILE__
, line
)(surface_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3953 "Got Format %#x, expected %#x.\n", surface_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3954 ok_(__FILE__
, line
)(surface_desc
.SampleDesc
.Count
== 1,
3955 "Got unexpected SampleDesc.Count %u.\n", surface_desc
.SampleDesc
.Count
);
3956 ok_(__FILE__
, line
)(!surface_desc
.SampleDesc
.Quality
,
3957 "Got unexpected SampleDesc.Quality %u.\n", surface_desc
.SampleDesc
.Quality
);
3960 #define check_texture_desc(a, b) check_texture_desc_(__LINE__, a, b)
3961 static void check_texture_desc_(unsigned int line
, ID3D10Texture2D
*texture
,
3962 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3964 D3D10_TEXTURE2D_DESC texture_desc
;
3966 ID3D10Texture2D_GetDesc(texture
, &texture_desc
);
3967 ok_(__FILE__
, line
)(texture_desc
.Width
== swapchain_desc
->BufferDesc
.Width
,
3968 "Got Width %u, expected %u.\n", texture_desc
.Width
, swapchain_desc
->BufferDesc
.Width
);
3969 ok_(__FILE__
, line
)(texture_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
3970 "Got Height %u, expected %u.\n", texture_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
3971 ok_(__FILE__
, line
)(texture_desc
.MipLevels
== 1, "Got unexpected MipLevels %u.\n", texture_desc
.MipLevels
);
3972 ok_(__FILE__
, line
)(texture_desc
.ArraySize
== 1, "Got unexpected ArraySize %u.\n", texture_desc
.ArraySize
);
3973 ok_(__FILE__
, line
)(texture_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
3974 "Got Format %#x, expected %#x.\n", texture_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
3975 ok_(__FILE__
, line
)(texture_desc
.SampleDesc
.Count
== 1,
3976 "Got unexpected SampleDesc.Count %u.\n", texture_desc
.SampleDesc
.Count
);
3977 ok_(__FILE__
, line
)(!texture_desc
.SampleDesc
.Quality
,
3978 "Got unexpected SampleDesc.Quality %u.\n", texture_desc
.SampleDesc
.Quality
);
3979 ok_(__FILE__
, line
)(texture_desc
.Usage
== D3D10_USAGE_DEFAULT
,
3980 "Got unexpected Usage %#x.\n", texture_desc
.Usage
);
3981 ok_(__FILE__
, line
)(texture_desc
.BindFlags
== D3D10_BIND_RENDER_TARGET
,
3982 "Got unexpected BindFlags %#x.\n", texture_desc
.BindFlags
);
3983 ok_(__FILE__
, line
)(!texture_desc
.CPUAccessFlags
,
3984 "Got unexpected CPUAccessFlags %#x.\n", texture_desc
.CPUAccessFlags
);
3985 ok_(__FILE__
, line
)(!texture_desc
.MiscFlags
, "Got unexpected MiscFlags %#x.\n", texture_desc
.MiscFlags
);
3988 #define check_resource_desc(a, b) check_resource_desc_(__LINE__, a, b)
3989 static void check_resource_desc_(unsigned int line
, ID3D12Resource
*resource
,
3990 const DXGI_SWAP_CHAIN_DESC
*swapchain_desc
)
3992 D3D12_RESOURCE_DESC resource_desc
;
3994 resource_desc
= ID3D12Resource_GetDesc(resource
);
3995 ok_(__FILE__
, line
)(resource_desc
.Dimension
== D3D12_RESOURCE_DIMENSION_TEXTURE2D
,
3996 "Got unexpected Dimension %#x.\n", resource_desc
.Dimension
);
3997 ok_(__FILE__
, line
)(resource_desc
.Width
== swapchain_desc
->BufferDesc
.Width
, "Got Width %s, expected %u.\n",
3998 wine_dbgstr_longlong(resource_desc
.Width
), swapchain_desc
->BufferDesc
.Width
);
3999 ok_(__FILE__
, line
)(resource_desc
.Height
== swapchain_desc
->BufferDesc
.Height
,
4000 "Got Height %u, expected %u.\n", resource_desc
.Height
, swapchain_desc
->BufferDesc
.Height
);
4001 ok_(__FILE__
, line
)(resource_desc
.DepthOrArraySize
== 1,
4002 "Got unexpected DepthOrArraySize %u.\n", resource_desc
.DepthOrArraySize
);
4003 ok_(__FILE__
, line
)(resource_desc
.MipLevels
== 1,
4004 "Got unexpected MipLevels %u.\n", resource_desc
.MipLevels
);
4005 ok_(__FILE__
, line
)(resource_desc
.Format
== swapchain_desc
->BufferDesc
.Format
,
4006 "Got Format %#x, expected %#x.\n", resource_desc
.Format
, swapchain_desc
->BufferDesc
.Format
);
4007 ok_(__FILE__
, line
)(resource_desc
.SampleDesc
.Count
== 1,
4008 "Got unexpected SampleDesc.Count %u.\n", resource_desc
.SampleDesc
.Count
);
4009 ok_(__FILE__
, line
)(!resource_desc
.SampleDesc
.Quality
,
4010 "Got unexpected SampleDesc.Quality %u.\n", resource_desc
.SampleDesc
.Quality
);
4011 ok_(__FILE__
, line
)(resource_desc
.Layout
== D3D12_TEXTURE_LAYOUT_UNKNOWN
,
4012 "Got unexpected Layout %#x.\n", resource_desc
.Layout
);
4015 static void test_swapchain_resize(IUnknown
*device
, BOOL is_d3d12
)
4017 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4018 DXGI_SWAP_EFFECT swap_effect
;
4019 IDXGISwapChain3
*swapchain3
;
4020 IUnknown
*present_queue
[2];
4021 IDXGISwapChain
*swapchain
;
4022 ID3D12Resource
*resource
;
4023 ID3D10Texture2D
*texture
;
4024 HRESULT hr
, expected_hr
;
4025 IDXGISurface
*surface
;
4026 IDXGIFactory
*factory
;
4027 RECT client_rect
, r
;
4033 get_factory(device
, is_d3d12
, &factory
);
4035 window
= create_window();
4036 ret
= GetClientRect(window
, &client_rect
);
4037 ok(ret
, "Failed to get client rect.\n");
4039 swap_effect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4041 swapchain_desc
.BufferDesc
.Width
= 640;
4042 swapchain_desc
.BufferDesc
.Height
= 480;
4043 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4044 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
4045 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4046 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4047 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4048 swapchain_desc
.SampleDesc
.Count
= 1;
4049 swapchain_desc
.SampleDesc
.Quality
= 0;
4050 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4051 swapchain_desc
.BufferCount
= 2;
4052 swapchain_desc
.OutputWindow
= window
;
4053 swapchain_desc
.Windowed
= TRUE
;
4054 swapchain_desc
.SwapEffect
= swap_effect
;
4055 swapchain_desc
.Flags
= 0;
4057 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4058 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4059 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4060 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4061 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4062 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4063 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4064 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4065 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4066 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4067 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4068 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4069 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4071 ret
= GetClientRect(window
, &r
);
4072 ok(ret
, "Failed to get client rect.\n");
4073 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4074 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4076 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4077 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4078 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4079 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4080 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4081 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4082 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4083 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4084 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4085 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4086 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4087 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4088 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4089 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4090 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4091 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4092 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4093 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4094 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4095 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4096 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4097 ok(!swapchain_desc
.SampleDesc
.Quality
,
4098 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4099 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4100 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4101 ok(swapchain_desc
.BufferCount
== 2,
4102 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4103 ok(swapchain_desc
.OutputWindow
== window
,
4104 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4105 ok(swapchain_desc
.Windowed
,
4106 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4107 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4108 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4109 ok(!swapchain_desc
.Flags
,
4110 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4113 check_surface_desc(surface
, &swapchain_desc
);
4115 check_texture_desc(texture
, &swapchain_desc
);
4117 check_resource_desc(resource
, &swapchain_desc
);
4119 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4120 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4122 ret
= GetClientRect(window
, &r
);
4123 ok(ret
, "Failed to get client rect.\n");
4124 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4125 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4127 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4128 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4129 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4130 ok(swapchain_desc
.BufferDesc
.Width
== 640,
4131 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4132 ok(swapchain_desc
.BufferDesc
.Height
== 480,
4133 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4134 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4135 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4136 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4137 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4138 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4139 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4140 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_R8G8B8A8_UNORM
,
4141 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4142 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4143 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4144 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4145 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4146 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4147 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4148 ok(!swapchain_desc
.SampleDesc
.Quality
,
4149 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4150 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4151 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4152 ok(swapchain_desc
.BufferCount
== 2,
4153 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4154 ok(swapchain_desc
.OutputWindow
== window
,
4155 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4156 ok(swapchain_desc
.Windowed
,
4157 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4158 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4159 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4160 ok(!swapchain_desc
.Flags
,
4161 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4165 check_surface_desc(surface
, &swapchain_desc
);
4166 IDXGISurface_Release(surface
);
4170 check_texture_desc(texture
, &swapchain_desc
);
4171 ID3D10Texture2D_Release(texture
);
4175 check_resource_desc(resource
, &swapchain_desc
);
4176 ID3D12Resource_Release(resource
);
4179 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0);
4180 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4181 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGISurface
, (void **)&surface
);
4182 expected_hr
= is_d3d12
? E_NOINTERFACE
: S_OK
;
4183 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4184 ok(!surface
|| hr
== S_OK
, "Got unexpected pointer %p.\n", surface
);
4185 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&texture
);
4186 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4187 ok(!texture
|| hr
== S_OK
, "Got unexpected pointer %p.\n", texture
);
4188 expected_hr
= is_d3d12
? S_OK
: E_NOINTERFACE
;
4189 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D12Resource
, (void **)&resource
);
4190 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4191 ok(!resource
|| hr
== S_OK
, "Got unexpected pointer %p.\n", resource
);
4193 ret
= GetClientRect(window
, &r
);
4194 ok(ret
, "Failed to get client rect.\n");
4195 ok(EqualRect(&r
, &client_rect
), "Got unexpected rect %s, expected %s.\n",
4196 wine_dbgstr_rect(&r
), wine_dbgstr_rect(&client_rect
));
4198 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4199 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4200 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4201 ok(swapchain_desc
.BufferDesc
.Width
== 320,
4202 "Got unexpected BufferDesc.Width %u.\n", swapchain_desc
.BufferDesc
.Width
);
4203 ok(swapchain_desc
.BufferDesc
.Height
== 240,
4204 "Got unexpected bufferDesc.Height %u.\n", swapchain_desc
.BufferDesc
.Height
);
4205 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4206 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4207 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4208 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4209 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4210 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4211 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4212 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4213 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4214 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4215 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4216 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4217 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4218 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4219 ok(!swapchain_desc
.SampleDesc
.Quality
,
4220 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4221 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4222 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4223 ok(swapchain_desc
.BufferCount
== 2,
4224 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4225 ok(swapchain_desc
.OutputWindow
== window
,
4226 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4227 ok(swapchain_desc
.Windowed
,
4228 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4229 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4230 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4231 ok(!swapchain_desc
.Flags
,
4232 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4236 check_surface_desc(surface
, &swapchain_desc
);
4237 IDXGISurface_Release(surface
);
4241 check_texture_desc(texture
, &swapchain_desc
);
4242 ID3D10Texture2D_Release(texture
);
4246 check_resource_desc(resource
, &swapchain_desc
);
4247 ID3D12Resource_Release(resource
);
4250 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4251 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4253 memset(&swapchain_desc
, 0, sizeof(swapchain_desc
));
4254 hr
= IDXGISwapChain_GetDesc(swapchain
, &swapchain_desc
);
4255 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4256 ok(swapchain_desc
.BufferDesc
.Width
== client_rect
.right
- client_rect
.left
,
4257 "Got unexpected BufferDesc.Width %u, expected %lu.\n",
4258 swapchain_desc
.BufferDesc
.Width
, client_rect
.right
- client_rect
.left
);
4259 ok(swapchain_desc
.BufferDesc
.Height
== client_rect
.bottom
- client_rect
.top
,
4260 "Got unexpected bufferDesc.Height %u, expected %lu.\n",
4261 swapchain_desc
.BufferDesc
.Height
, client_rect
.bottom
- client_rect
.top
);
4262 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
== 60,
4263 "Got unexpected BufferDesc.RefreshRate.Numerator %u.\n",
4264 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
);
4265 ok(swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
== 1,
4266 "Got unexpected BufferDesc.RefreshRate.Denominator %u.\n",
4267 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
);
4268 ok(swapchain_desc
.BufferDesc
.Format
== DXGI_FORMAT_B8G8R8A8_UNORM
,
4269 "Got unexpected BufferDesc.Format %#x.\n", swapchain_desc
.BufferDesc
.Format
);
4270 ok(swapchain_desc
.BufferDesc
.ScanlineOrdering
== DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
,
4271 "Got unexpected BufferDesc.ScanlineOrdering %#x.\n", swapchain_desc
.BufferDesc
.ScanlineOrdering
);
4272 ok(swapchain_desc
.BufferDesc
.Scaling
== DXGI_MODE_SCALING_UNSPECIFIED
,
4273 "Got unexpected BufferDesc.Scaling %#x.\n", swapchain_desc
.BufferDesc
.Scaling
);
4274 ok(swapchain_desc
.SampleDesc
.Count
== 1,
4275 "Got unexpected SampleDesc.Count %u.\n", swapchain_desc
.SampleDesc
.Count
);
4276 ok(!swapchain_desc
.SampleDesc
.Quality
,
4277 "Got unexpected SampleDesc.Quality %u.\n", swapchain_desc
.SampleDesc
.Quality
);
4278 ok(swapchain_desc
.BufferUsage
== DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4279 "Got unexpected BufferUsage %#x.\n", swapchain_desc
.BufferUsage
);
4280 ok(swapchain_desc
.BufferCount
== 2,
4281 "Got unexpected BufferCount %u.\n", swapchain_desc
.BufferCount
);
4282 ok(swapchain_desc
.OutputWindow
== window
,
4283 "Got unexpected OutputWindow %p, expected %p.\n", swapchain_desc
.OutputWindow
, window
);
4284 ok(swapchain_desc
.Windowed
,
4285 "Got unexpected Windowed %#x.\n", swapchain_desc
.Windowed
);
4286 ok(swapchain_desc
.SwapEffect
== swap_effect
,
4287 "Got unexpected SwapEffect %#x.\n", swapchain_desc
.SwapEffect
);
4288 ok(!swapchain_desc
.Flags
,
4289 "Got unexpected Flags %#x.\n", swapchain_desc
.Flags
);
4293 present_queue
[0] = device
;
4294 present_queue
[1] = device
;
4295 if (IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
) == E_NOINTERFACE
)
4297 skip("IDXGISwapChain3 is not supported.\n");
4301 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4302 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4303 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4304 IDXGISwapChain3_Release(swapchain3
);
4308 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4309 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4310 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4311 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4312 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, present_queue
);
4313 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4314 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4315 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4316 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240, DXGI_FORMAT_B8G8R8A8_UNORM
, 0, NULL
, NULL
);
4317 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4320 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 2, 320, 240,
4321 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4322 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4323 /* Windows validates node masks even when the buffer count is zero.
4324 * It defaults to the current buffer count. NULL queues cause some
4325 * Windows versions to crash. */
4326 hr
= IDXGISwapChain3_ResizeBuffers1(swapchain3
, 0, 320, 240,
4327 DXGI_FORMAT_B8G8R8A8_UNORM
, 0, node_mask
, present_queue
);
4328 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4329 IDXGISwapChain3_Release(swapchain3
);
4332 IDXGISwapChain_Release(swapchain
);
4333 DestroyWindow(window
);
4334 refcount
= IDXGIFactory_Release(factory
);
4335 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4338 static void test_swapchain_parameters(void)
4340 DXGI_USAGE usage
, expected_usage
, broken_usage
;
4341 D3D10_TEXTURE2D_DESC d3d10_texture_desc
;
4342 D3D11_TEXTURE2D_DESC d3d11_texture_desc
;
4343 unsigned int expected_bind_flags
;
4344 ID3D10Texture2D
*d3d10_texture
;
4345 ID3D11Texture2D
*d3d11_texture
;
4346 DXGI_SWAP_CHAIN_DESC desc
;
4347 IDXGISwapChain
*swapchain
;
4348 IDXGIResource
*resource
;
4349 IDXGIAdapter
*adapter
;
4350 IDXGIFactory
*factory
;
4351 IDXGIDevice
*device
;
4362 DXGI_SWAP_EFFECT swap_effect
;
4363 HRESULT hr
, vista_hr
;
4364 UINT highest_accessible_buffer
;
4369 {TRUE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4370 {TRUE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4371 {TRUE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4372 {TRUE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4373 {TRUE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4375 {TRUE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4376 {TRUE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4377 {TRUE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4378 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4379 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4381 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4382 {TRUE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4383 {TRUE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4384 {TRUE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4385 {TRUE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4387 {TRUE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4388 {TRUE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4389 {TRUE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4390 {TRUE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4391 {TRUE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4393 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4394 {TRUE
, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4395 {TRUE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4396 {FALSE
, 1, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4397 {FALSE
, 2, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4399 {FALSE
, 1, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 0},
4400 {FALSE
, 2, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 1},
4401 {FALSE
, 3, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 2},
4402 {FALSE
, 0, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4403 {FALSE
, 1, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4405 {FALSE
, 2, 2 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4406 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4407 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4408 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 1},
4409 {FALSE
, 3, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 2},
4411 {FALSE
, 0, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4412 {FALSE
, 1, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4413 {FALSE
, 2, DXGI_SWAP_EFFECT_FLIP_DISCARD
, S_OK
, DXGI_ERROR_INVALID_CALL
, 0},
4414 {FALSE
, 0, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4415 {FALSE
, 1, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4417 {FALSE
, 2, 5 /* undefined */, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4418 {FALSE
, 16, DXGI_SWAP_EFFECT_DISCARD
, S_OK
, S_OK
, 0},
4419 {FALSE
, 16, DXGI_SWAP_EFFECT_SEQUENTIAL
, S_OK
, S_OK
, 15},
4420 {FALSE
, 16, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, S_OK
, DXGI_ERROR_INVALID_CALL
, 15},
4421 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4423 {FALSE
, 17, DXGI_SWAP_EFFECT_FLIP_DISCARD
, DXGI_ERROR_INVALID_CALL
, DXGI_ERROR_INVALID_CALL
, 0},
4425 /* The following test fails on Nvidia with E_OUTOFMEMORY and leaks device references in the
4426 * process. Disable it for now.
4427 {FALSE, 16, DXGI_SWAP_EFFECT_FLIP_DISCARD, S_OK, DXGI_ERROR_INVALID_CALL, 0},
4430 /* The following tests crash on Win10 1909
4431 {TRUE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4432 {TRUE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4433 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4434 {TRUE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4435 {TRUE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4436 {FALSE, 0, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4437 {FALSE, 0, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4438 {FALSE, 17, DXGI_SWAP_EFFECT_DISCARD, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4439 {FALSE, 17, DXGI_SWAP_EFFECT_SEQUENTIAL, DXGI_ERROR_INVALID_CALL, DXGI_ERROR_INVALID_CALL, 0},
4442 static const DXGI_USAGE usage_tests
[] =
4445 DXGI_USAGE_BACK_BUFFER
,
4446 DXGI_USAGE_SHADER_INPUT
,
4447 DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4448 DXGI_USAGE_DISCARD_ON_PRESENT
,
4449 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
,
4450 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4451 DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4452 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
,
4453 DXGI_USAGE_SHADER_INPUT
| DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_DISCARD_ON_PRESENT
,
4456 if (!(device
= create_device(0)))
4458 skip("Failed to create device.\n");
4461 window
= create_window();
4463 hr
= IDXGIDevice_QueryInterface(device
, &IID_IUnknown
, (void **)&obj
);
4464 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4466 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
4467 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4468 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
4469 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4470 IDXGIAdapter_Release(adapter
);
4472 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
4474 memset(&desc
, 0, sizeof(desc
));
4475 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4476 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4477 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4478 desc
.SampleDesc
.Count
= 1;
4479 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4480 desc
.OutputWindow
= window
;
4482 desc
.Windowed
= tests
[i
].windowed
;
4483 desc
.BufferCount
= tests
[i
].buffer_count
;
4484 desc
.SwapEffect
= tests
[i
].swap_effect
;
4486 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4487 ok(hr
== tests
[i
].hr
|| broken(hr
== tests
[i
].vista_hr
)
4488 || (SUCCEEDED(tests
[i
].hr
) && hr
== DXGI_STATUS_OCCLUDED
),
4489 "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4493 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4494 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4496 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4497 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4499 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4501 ok((usage
& expected_usage
) == expected_usage
, "Got usage %x, expected %x, test %u.\n",
4502 usage
, expected_usage
, i
);
4504 IDXGIResource_Release(resource
);
4506 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4507 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4509 for (j
= 1; j
<= tests
[i
].highest_accessible_buffer
; j
++)
4511 hr
= IDXGISwapChain_GetBuffer(swapchain
, j
, &IID_IDXGIResource
, (void **)&resource
);
4512 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u, buffer %u.\n", hr
, i
, j
);
4514 /* Buffers > 0 are supposed to be read only. This is the case except that in
4515 * fullscreen mode on Windows <= 8 the last backbuffer (BufferCount - 1) is
4516 * writable. This is not the case if an unsupported refresh rate is passed
4517 * for some reason, probably because the invalid refresh rate triggers a
4518 * kinda-sorta windowed mode.
4520 * On Windows 10 all buffers > 0 are read-only. Mark the earlier behavior
4523 * This last buffer acts as a shadow frontbuffer. Writing to it doesn't show
4524 * the draw on the screen right away (Aero on or off doesn't matter), but
4525 * Present with DXGI_PRESENT_DO_NOT_SEQUENCE will show the modifications.
4527 * Note that if the application doesn't have focus creating a fullscreen
4528 * swapchain returns DXGI_STATUS_OCCLUDED and we get a windowed swapchain,
4529 * so use the Windowed property of the swapchain that was actually created. */
4530 expected_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_READ_ONLY
;
4531 broken_usage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_BACK_BUFFER
;
4533 if (desc
.Windowed
|| j
< tests
[i
].highest_accessible_buffer
)
4534 broken_usage
|= DXGI_USAGE_READ_ONLY
;
4536 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4538 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u, buffer %u.\n", hr
, i
, j
);
4540 ok(usage
== expected_usage
|| broken(usage
== broken_usage
),
4541 "Got usage %x, expected %x, test %u, buffer %u.\n",
4542 usage
, expected_usage
, i
, j
);
4544 IDXGIResource_Release(resource
);
4547 if (strcmp(winetest_platform
, "wine"))
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
);
4553 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4554 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4556 IDXGISwapChain_Release(swapchain
);
4559 for (i
= 0; i
< ARRAY_SIZE(usage_tests
); ++i
)
4561 usage
= usage_tests
[i
];
4563 memset(&desc
, 0, sizeof(desc
));
4564 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4565 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4566 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4567 desc
.SampleDesc
.Count
= 1;
4568 desc
.BufferUsage
= usage
;
4569 desc
.BufferCount
= 1;
4570 desc
.OutputWindow
= window
;
4571 desc
.Windowed
= TRUE
;
4572 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4573 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4574 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4576 hr
= IDXGISwapChain_GetDesc(swapchain
, &desc
);
4577 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4578 todo_wine_if(usage
& ~(DXGI_USAGE_RENDER_TARGET_OUTPUT
| DXGI_USAGE_SHADER_INPUT
))
4579 ok(desc
.BufferUsage
== usage
, "Got usage %#x, expected %#x, test %u.\n", desc
.BufferUsage
, usage
, i
);
4581 expected_bind_flags
= 0;
4582 if (usage
& DXGI_USAGE_RENDER_TARGET_OUTPUT
)
4583 expected_bind_flags
|= D3D11_BIND_RENDER_TARGET
;
4584 if (usage
& DXGI_USAGE_SHADER_INPUT
)
4585 expected_bind_flags
|= D3D11_BIND_SHADER_RESOURCE
;
4587 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D10Texture2D
, (void **)&d3d10_texture
);
4588 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4589 ID3D10Texture2D_GetDesc(d3d10_texture
, &d3d10_texture_desc
);
4590 ok(d3d10_texture_desc
.BindFlags
== expected_bind_flags
,
4591 "Got d3d10 bind flags %#x, expected %#x, test %u.\n",
4592 d3d10_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4593 ID3D10Texture2D_Release(d3d10_texture
);
4595 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_ID3D11Texture2D
, (void **)&d3d11_texture
);
4596 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4599 ID3D11Texture2D_GetDesc(d3d11_texture
, &d3d11_texture_desc
);
4600 ok(d3d11_texture_desc
.BindFlags
== expected_bind_flags
,
4601 "Got d3d11 bind flags %#x, expected %#x, test %u.\n",
4602 d3d11_texture_desc
.BindFlags
, expected_bind_flags
, i
);
4603 ID3D11Texture2D_Release(d3d11_texture
);
4606 hr
= IDXGISwapChain_GetBuffer(swapchain
, 0, &IID_IDXGIResource
, (void **)&resource
);
4607 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4608 expected_usage
= usage
| DXGI_USAGE_BACK_BUFFER
| DXGI_USAGE_DISCARD_ON_PRESENT
;
4609 hr
= IDXGIResource_GetUsage(resource
, &usage
);
4611 ok(hr
== S_OK
, "Got unexpected hr %#lx, test %u.\n", hr
, i
);
4612 todo_wine_if(i
!= 7)
4613 ok(usage
== expected_usage
, "Got usage %x, expected %x, test %u.\n", usage
, expected_usage
, i
);
4614 IDXGIResource_Release(resource
);
4616 IDXGISwapChain_Release(swapchain
);
4620 memset(&desc
, 0, sizeof(desc
));
4621 desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
4622 desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
4623 desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4624 desc
.SampleDesc
.Count
= 4;
4625 desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4626 desc
.BufferCount
= 4;
4627 desc
.OutputWindow
= window
;
4628 desc
.Windowed
= TRUE
;
4629 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
;
4630 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4631 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4632 desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
4633 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4634 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
4635 if (check_multisample_quality_levels(device
, desc
.BufferDesc
.Format
, desc
.SampleDesc
.Count
))
4637 desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4638 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4639 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4640 IDXGISwapChain_Release(swapchain
);
4641 desc
.SwapEffect
= DXGI_SWAP_EFFECT_SEQUENTIAL
;
4642 hr
= IDXGIFactory_CreateSwapChain(factory
, obj
, &desc
, &swapchain
);
4643 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4644 IDXGISwapChain_Release(swapchain
);
4648 skip("Multisampling not supported for DXGI_FORMAT_R8G8B8A8_UNORM.\n");
4651 IDXGIFactory_Release(factory
);
4652 IUnknown_Release(obj
);
4653 refcount
= IDXGIDevice_Release(device
);
4654 ok(!refcount
, "Device has %lu references left.\n", refcount
);
4655 DestroyWindow(window
);
4658 static void test_swapchain_present(IUnknown
*device
, BOOL is_d3d12
)
4660 static const DWORD flags
[] = {0, DXGI_PRESENT_TEST
};
4661 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4662 IDXGISwapChain
*swapchain
;
4663 IDXGIFactory
*factory
;
4664 IDXGIOutput
*output
;
4670 get_factory(device
, is_d3d12
, &factory
);
4672 swapchain_desc
.BufferDesc
.Width
= 800;
4673 swapchain_desc
.BufferDesc
.Height
= 600;
4674 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4675 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4676 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4677 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4678 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4679 swapchain_desc
.SampleDesc
.Count
= 1;
4680 swapchain_desc
.SampleDesc
.Quality
= 0;
4681 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4682 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
4683 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
4684 swapchain_desc
.Windowed
= TRUE
;
4685 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
4686 swapchain_desc
.Flags
= 0;
4688 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4689 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4691 for (i
= 0; i
< 10; ++i
)
4693 hr
= IDXGISwapChain_Present(swapchain
, i
, 0);
4694 ok(hr
== (i
<= 4 ? S_OK
: DXGI_ERROR_INVALID_CALL
),
4695 "Got unexpected hr %#lx for sync interval %u.\n", hr
, i
);
4697 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4698 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4700 for (i
= 0; i
< ARRAY_SIZE(flags
); ++i
)
4702 HWND occluding_window
= CreateWindowA("static", "occluding_window",
4703 WS_POPUP
| WS_VISIBLE
, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
4705 /* Another window covers the swapchain window. Not reported as occluded. */
4706 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4707 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4709 /* Minimised window. */
4710 ShowWindow(swapchain_desc
.OutputWindow
, SW_MINIMIZE
);
4711 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4712 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4713 ShowWindow(swapchain_desc
.OutputWindow
, SW_NORMAL
);
4715 /* Hidden window. */
4716 ShowWindow(swapchain_desc
.OutputWindow
, SW_HIDE
);
4717 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4718 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4719 ShowWindow(swapchain_desc
.OutputWindow
, SW_SHOW
);
4720 DestroyWindow(occluding_window
);
4722 /* Test that IDXGIOutput_ReleaseOwnership() makes the swapchain exit
4724 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4725 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
4726 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
4727 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
4729 skip("Test %u: Could not change fullscreen state.\n", i
);
4733 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4734 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4735 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4736 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4737 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4740 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
4741 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4742 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4743 ok(!!output
, "Test %u: Got unexpected output.\n", i
);
4746 IDXGIOutput_ReleaseOwnership(output
);
4747 /* Still fullscreen. */
4749 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4750 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4751 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4752 /* Calling IDXGISwapChain_Present() will exit fullscreen. */
4753 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4754 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4756 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4757 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4758 /* Now fullscreen mode is exited. */
4759 if (!flags
[i
] && !is_d3d12
)
4760 /* Still fullscreen on vista and 2008. */
4761 todo_wine
ok(!fullscreen
|| broken(fullscreen
), "Test %u: Got unexpected fullscreen status.\n", i
);
4763 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4765 IDXGIOutput_Release(output
);
4767 /* Test creating a window when swapchain is in fullscreen.
4769 * The window should break the swapchain out of fullscreen mode on
4770 * d3d10/11. D3d12 is different, a new occluding window doesn't break
4771 * the swapchain out of fullscreen because d3d12 fullscreen swapchains
4772 * don't take exclusive ownership over the output, nor do they disable
4773 * compositing. D3d12 fullscreen mode acts just like borderless
4774 * fullscreen window mode. */
4775 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4776 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4778 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4779 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4780 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4781 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4782 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4783 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4784 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4786 occluding_window
= CreateWindowA("static", "occluding_window", WS_POPUP
, 0, 0, 400, 200, 0, 0, 0, 0);
4787 /* An invisible window doesn't cause the swapchain to exit fullscreen
4789 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4790 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4791 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4792 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4794 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4795 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4796 ok(fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4797 /* A visible, but with bottom z-order window still causes the
4798 * swapchain to exit fullscreen mode. */
4799 SetWindowPos(occluding_window
, HWND_BOTTOM
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
4800 ShowWindow(occluding_window
, SW_SHOW
);
4801 /* Fullscreen mode takes a while to exit. */
4803 wait_fullscreen_state(swapchain
, FALSE
, TRUE
);
4805 /* No longer fullscreen before calling IDXGISwapChain_Present() except
4808 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4809 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4810 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4811 "Test %u: Got unexpected fullscreen status.\n", i
);
4813 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4814 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4815 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4816 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4817 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4820 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4821 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4822 if (flags
[i
] == DXGI_PRESENT_TEST
)
4823 todo_wine_if(!is_d3d12
) ok(is_d3d12
? fullscreen
: !fullscreen
,
4824 "Test %u: Got unexpected fullscreen status.\n", i
);
4826 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4828 /* Even though d3d12 doesn't exit fullscreen, a
4829 * IDXGISwapChain_ResizeBuffers() is still needed for subsequent
4830 * IDXGISwapChain_Present() calls to work, otherwise they will return
4831 * DXGI_ERROR_INVALID_CALL */
4832 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4833 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4834 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4835 if (flags
[i
] == DXGI_PRESENT_TEST
)
4836 todo_wine_if(is_d3d12
) ok(hr
== (is_d3d12
? DXGI_STATUS_OCCLUDED
: S_OK
),
4837 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4839 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4841 /* Trying to break out of fullscreen mode again. This time, don't call
4842 * IDXGISwapChain_GetFullscreenState() before IDXGISwapChain_Present(). */
4843 ShowWindow(occluding_window
, SW_HIDE
);
4844 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
4845 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4846 ShowWindow(occluding_window
, SW_SHOW
);
4848 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4849 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4850 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4851 /* hr == S_OK on vista and 2008 */
4852 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4853 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4855 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4856 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4857 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4858 if (flags
[i
] == DXGI_PRESENT_TEST
)
4860 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4861 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4862 /* IDXGISwapChain_Present() without flags refreshes the occlusion
4864 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4865 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4866 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
4867 todo_wine
ok(hr
== DXGI_STATUS_OCCLUDED
|| broken(hr
== S_OK
),
4868 "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4869 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4870 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4871 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
4872 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4876 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4879 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
4880 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4881 todo_wine
ok(!fullscreen
, "Test %u: Got unexpected fullscreen status.\n", i
);
4883 DestroyWindow(occluding_window
);
4885 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4886 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4887 hr
= IDXGISwapChain_Present(swapchain
, 0, flags
[i
]);
4888 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4890 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
4891 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4892 hr
= IDXGISwapChain_ResizeBuffers(swapchain
, 0, 0, 0, DXGI_FORMAT_UNKNOWN
, 0);
4893 ok(hr
== S_OK
, "Test %u: Got unexpected hr %#lx.\n", i
, hr
);
4896 wait_device_idle(device
);
4898 IDXGISwapChain_Release(swapchain
);
4899 DestroyWindow(swapchain_desc
.OutputWindow
);
4900 refcount
= IDXGIFactory_Release(factory
);
4901 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4904 static void test_swapchain_backbuffer_index(IUnknown
*device
, BOOL is_d3d12
)
4906 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4907 unsigned int index
, expected_index
;
4908 IDXGISwapChain3
*swapchain3
;
4909 IDXGISwapChain
*swapchain
;
4910 HRESULT hr
, expected_hr
;
4911 IDXGIFactory
*factory
;
4917 static const DXGI_SWAP_EFFECT swap_effects
[] =
4919 DXGI_SWAP_EFFECT_DISCARD
,
4920 DXGI_SWAP_EFFECT_SEQUENTIAL
,
4921 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
,
4922 DXGI_SWAP_EFFECT_FLIP_DISCARD
,
4925 get_factory(device
, is_d3d12
, &factory
);
4927 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
4928 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
4929 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
4930 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
4931 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
4932 swapchain_desc
.SampleDesc
.Count
= 1;
4933 swapchain_desc
.SampleDesc
.Quality
= 0;
4934 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
4935 swapchain_desc
.BufferCount
= 4;
4936 swapchain_desc
.OutputWindow
= create_window();
4937 swapchain_desc
.Windowed
= TRUE
;
4938 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
4939 swapchain_desc
.Flags
= 0;
4941 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
4942 ok(ret
, "Failed to get client rect.\n");
4943 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
4944 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
4946 for (i
= 0; i
< ARRAY_SIZE(swap_effects
); ++i
)
4948 swapchain_desc
.SwapEffect
= swap_effects
[i
];
4949 expected_hr
= is_d3d12
&& !is_flip_model(swap_effects
[i
]) ? DXGI_ERROR_INVALID_CALL
: S_OK
;
4950 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
4951 ok(hr
== expected_hr
, "Got unexpected hr %#lx, expected %#lx.\n", hr
, expected_hr
);
4955 hr
= IDXGISwapChain_QueryInterface(swapchain
, &IID_IDXGISwapChain3
, (void **)&swapchain3
);
4956 if (hr
== E_NOINTERFACE
)
4958 skip("IDXGISwapChain3 is not supported.\n");
4959 IDXGISwapChain_Release(swapchain
);
4963 for (j
= 0; j
< 2 * swapchain_desc
.BufferCount
; ++j
)
4965 index
= IDXGISwapChain3_GetCurrentBackBufferIndex(swapchain3
);
4966 expected_index
= is_d3d12
? j
% swapchain_desc
.BufferCount
: 0;
4967 ok(index
== expected_index
, "Got back buffer index %u, expected %u.\n", index
, expected_index
);
4968 hr
= IDXGISwapChain3_Present(swapchain3
, 0, 0);
4969 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
4972 wait_device_idle(device
);
4974 IDXGISwapChain3_Release(swapchain3
);
4975 refcount
= IDXGISwapChain_Release(swapchain
);
4976 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
4980 DestroyWindow(swapchain_desc
.OutputWindow
);
4981 refcount
= IDXGIFactory_Release(factory
);
4982 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
4985 static void test_swapchain_formats(IUnknown
*device
, BOOL is_d3d12
)
4987 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
4988 IDXGISwapChain
*swapchain
;
4989 HRESULT hr
, expected_hr
;
4990 IDXGIFactory
*factory
;
4999 DXGI_SWAP_EFFECT swap_effect
;
5004 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_DISCARD
, FALSE
},
5005 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_SEQUENTIAL
, FALSE
},
5006 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5007 {DXGI_FORMAT_UNKNOWN
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5008 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5009 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5010 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5011 {DXGI_FORMAT_R8G8B8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5012 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5013 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5014 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5015 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5016 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5017 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5018 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5019 {DXGI_FORMAT_B8G8R8A8_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5020 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5021 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5022 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5023 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5024 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5025 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5026 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5027 {DXGI_FORMAT_R10G10B10A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5028 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_DISCARD
, TRUE
},
5029 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_SEQUENTIAL
, TRUE
},
5030 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, TRUE
},
5031 {DXGI_FORMAT_R16G16B16A16_FLOAT
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, TRUE
},
5032 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_DISCARD
, FALSE
},
5033 {DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
, DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL
, FALSE
},
5036 get_factory(device
, is_d3d12
, &factory
);
5038 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5039 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5040 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5041 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5042 swapchain_desc
.SampleDesc
.Count
= 1;
5043 swapchain_desc
.SampleDesc
.Quality
= 0;
5044 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5045 swapchain_desc
.BufferCount
= 4;
5046 swapchain_desc
.OutputWindow
= create_window();
5047 swapchain_desc
.Windowed
= TRUE
;
5048 swapchain_desc
.Flags
= 0;
5050 ret
= GetClientRect(swapchain_desc
.OutputWindow
, &rect
);
5051 ok(ret
, "Failed to get client rect.\n");
5052 swapchain_desc
.BufferDesc
.Width
= rect
.right
;
5053 swapchain_desc
.BufferDesc
.Height
= rect
.bottom
;
5055 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
5057 if (is_d3d12
&& !is_flip_model(tests
[i
].swap_effect
))
5060 swapchain_desc
.BufferDesc
.Format
= tests
[i
].format
;
5061 swapchain_desc
.SwapEffect
= tests
[i
].swap_effect
;
5062 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
5063 expected_hr
= tests
[i
].supported
? S_OK
: DXGI_ERROR_INVALID_CALL
;
5064 if (tests
[i
].format
== DXGI_FORMAT_UNKNOWN
&& !is_d3d12
)
5065 expected_hr
= E_INVALIDARG
;
5066 ok(hr
== expected_hr
5067 /* Flip presentation model not supported. */
5068 || broken(hr
== DXGI_ERROR_INVALID_CALL
&& is_flip_model(tests
[i
].swap_effect
) && !is_d3d12
),
5069 "Test %u, d3d12 %#x: Got unexpected hr %#lx, expected %#lx.\n", i
, is_d3d12
, hr
, expected_hr
);
5073 refcount
= IDXGISwapChain_Release(swapchain
);
5074 ok(!refcount
, "Swapchain has %lu references left.\n", refcount
);
5078 DestroyWindow(swapchain_desc
.OutputWindow
);
5079 refcount
= IDXGIFactory_Release(factory
);
5080 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
5083 static void test_maximum_frame_latency(void)
5085 IDXGIDevice1
*device1
;
5086 IDXGIDevice
*device
;
5091 if (!(device
= create_device(0)))
5093 skip("Failed to create device.\n");
5097 if (SUCCEEDED(IDXGIDevice_QueryInterface(device
, &IID_IDXGIDevice1
, (void **)&device1
)))
5099 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, NULL
);
5100 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5102 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5103 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5104 ok(max_latency
== DEFAULT_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5106 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
);
5107 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5108 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5109 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5110 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5112 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, MAX_FRAME_LATENCY
+ 1);
5113 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5114 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5115 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5116 ok(max_latency
== MAX_FRAME_LATENCY
, "Got unexpected maximum frame latency %u.\n", max_latency
);
5118 hr
= IDXGIDevice1_SetMaximumFrameLatency(device1
, 0);
5119 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5120 hr
= IDXGIDevice1_GetMaximumFrameLatency(device1
, &max_latency
);
5121 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5122 /* 0 does not reset to the default frame latency on all Windows versions. */
5123 ok(max_latency
== DEFAULT_FRAME_LATENCY
|| broken(!max_latency
),
5124 "Got unexpected maximum frame latency %u.\n", max_latency
);
5126 IDXGIDevice1_Release(device1
);
5130 win_skip("IDXGIDevice1 is not implemented.\n");
5133 refcount
= IDXGIDevice_Release(device
);
5134 ok(!refcount
, "Device has %lu references left.\n", refcount
);
5137 static void test_output_desc(void)
5139 IDXGIAdapter
*adapter
, *adapter2
;
5140 IDXGIOutput
*output
, *output2
;
5141 DXGI_OUTPUT_DESC desc
;
5142 IDXGIFactory
*factory
;
5147 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5148 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5152 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter
);
5153 if (hr
== DXGI_ERROR_NOT_FOUND
)
5155 winetest_push_context("Adapter %u", i
);
5156 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5158 hr
= IDXGIFactory_EnumAdapters(factory
, i
, &adapter2
);
5159 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5160 ok(adapter
!= adapter2
, "Expected to get new instance of IDXGIAdapter, %p == %p.\n", adapter
, adapter2
);
5161 refcount
= get_refcount(adapter
);
5162 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5163 IDXGIAdapter_Release(adapter2
);
5165 refcount
= get_refcount(factory
);
5166 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5167 refcount
= get_refcount(adapter
);
5168 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5172 MONITORINFOEXW monitor_info
;
5175 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output
);
5176 if (hr
== DXGI_ERROR_NOT_FOUND
)
5178 winetest_push_context("Output %u", j
);
5179 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5181 hr
= IDXGIAdapter_EnumOutputs(adapter
, j
, &output2
);
5182 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5183 ok(output
!= output2
, "Expected to get new instance of IDXGIOutput, %p == %p.\n", output
, output2
);
5184 refcount
= get_refcount(output
);
5185 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5186 IDXGIOutput_Release(output2
);
5188 refcount
= get_refcount(factory
);
5189 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5190 refcount
= get_refcount(adapter
);
5191 ok(refcount
== 2, "Get unexpected refcount %lu.\n", refcount
);
5192 refcount
= get_refcount(output
);
5193 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5195 hr
= IDXGIOutput_GetDesc(output
, &desc
);
5196 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5198 monitor_info
.cbSize
= sizeof(monitor_info
);
5199 ret
= GetMonitorInfoW(desc
.Monitor
, (MONITORINFO
*)&monitor_info
);
5200 ok(ret
, "Failed to get monitor info.\n");
5201 ok(!lstrcmpW(desc
.DeviceName
, monitor_info
.szDevice
), "Got unexpected device name %s, expected %s.\n",
5202 wine_dbgstr_w(desc
.DeviceName
), wine_dbgstr_w(monitor_info
.szDevice
));
5203 ok(EqualRect(&desc
.DesktopCoordinates
, &monitor_info
.rcMonitor
),
5204 "Got unexpected desktop coordinates %s, expected %s.\n",
5205 wine_dbgstr_rect(&desc
.DesktopCoordinates
),
5206 wine_dbgstr_rect(&monitor_info
.rcMonitor
));
5208 IDXGIOutput_Release(output
);
5209 refcount
= get_refcount(adapter
);
5210 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5212 winetest_pop_context();
5215 IDXGIAdapter_Release(adapter
);
5216 refcount
= get_refcount(factory
);
5217 ok(refcount
== 1, "Get unexpected refcount %lu.\n", refcount
);
5219 winetest_pop_context();
5222 refcount
= IDXGIFactory_Release(factory
);
5223 ok(!refcount
, "IDXGIFactory has %lu references left.\n", refcount
);
5228 IDXGIFactory IDXGIFactory_iface
;
5229 IDXGIFactory
*wrapped_iface
;
5230 unsigned int wrapped_adapter_count
;
5233 static inline struct dxgi_factory
*impl_from_IDXGIFactory(IDXGIFactory
*iface
)
5235 return CONTAINING_RECORD(iface
, struct dxgi_factory
, IDXGIFactory_iface
);
5238 static HRESULT STDMETHODCALLTYPE
dxgi_factory_QueryInterface(IDXGIFactory
*iface
, REFIID iid
, void **out
)
5240 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5242 if (IsEqualGUID(iid
, &IID_IDXGIFactory
)
5243 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5244 || IsEqualGUID(iid
, &IID_IUnknown
))
5246 IDXGIFactory_AddRef(iface
);
5250 return IDXGIFactory_QueryInterface(factory
->wrapped_iface
, iid
, out
);
5253 static ULONG STDMETHODCALLTYPE
dxgi_factory_AddRef(IDXGIFactory
*iface
)
5255 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5256 return IDXGIFactory_AddRef(factory
->wrapped_iface
);
5259 static ULONG STDMETHODCALLTYPE
dxgi_factory_Release(IDXGIFactory
*iface
)
5261 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5262 return IDXGIFactory_Release(factory
->wrapped_iface
);
5265 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateData(IDXGIFactory
*iface
,
5266 REFGUID guid
, UINT data_size
, const void *data
)
5268 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5269 return IDXGIFactory_SetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5272 static HRESULT STDMETHODCALLTYPE
dxgi_factory_SetPrivateDataInterface(IDXGIFactory
*iface
,
5273 REFGUID guid
, const IUnknown
*object
)
5275 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5276 return IDXGIFactory_SetPrivateDataInterface(factory
->wrapped_iface
, guid
, object
);
5279 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetPrivateData(IDXGIFactory
*iface
,
5280 REFGUID guid
, UINT
*data_size
, void *data
)
5282 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5283 return IDXGIFactory_GetPrivateData(factory
->wrapped_iface
, guid
, data_size
, data
);
5286 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetParent(IDXGIFactory
*iface
, REFIID iid
, void **parent
)
5288 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5289 return IDXGIFactory_GetParent(factory
->wrapped_iface
, iid
, parent
);
5292 static HRESULT STDMETHODCALLTYPE
dxgi_factory_EnumAdapters(IDXGIFactory
*iface
,
5293 UINT adapter_idx
, IDXGIAdapter
**adapter
)
5295 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5298 if (SUCCEEDED(hr
= IDXGIFactory_EnumAdapters(factory
->wrapped_iface
, adapter_idx
, adapter
)))
5299 ++factory
->wrapped_adapter_count
;
5303 static HRESULT STDMETHODCALLTYPE
dxgi_factory_MakeWindowAssociation(IDXGIFactory
*iface
,
5304 HWND window
, UINT flags
)
5306 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5307 return IDXGIFactory_MakeWindowAssociation(factory
->wrapped_iface
, window
, flags
);
5310 static HRESULT STDMETHODCALLTYPE
dxgi_factory_GetWindowAssociation(IDXGIFactory
*iface
, HWND
*window
)
5312 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5313 return IDXGIFactory_GetWindowAssociation(factory
->wrapped_iface
, window
);
5316 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSwapChain(IDXGIFactory
*iface
,
5317 IUnknown
*device
, DXGI_SWAP_CHAIN_DESC
*desc
, IDXGISwapChain
**swapchain
)
5319 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5320 return IDXGIFactory_CreateSwapChain(factory
->wrapped_iface
, device
, desc
, swapchain
);
5323 static HRESULT STDMETHODCALLTYPE
dxgi_factory_CreateSoftwareAdapter(IDXGIFactory
*iface
,
5324 HMODULE swrast
, IDXGIAdapter
**adapter
)
5326 struct dxgi_factory
*factory
= impl_from_IDXGIFactory(iface
);
5327 return IDXGIFactory_CreateSoftwareAdapter(factory
->wrapped_iface
, swrast
, adapter
);
5330 static const struct IDXGIFactoryVtbl dxgi_factory_vtbl
=
5332 dxgi_factory_QueryInterface
,
5333 dxgi_factory_AddRef
,
5334 dxgi_factory_Release
,
5335 dxgi_factory_SetPrivateData
,
5336 dxgi_factory_SetPrivateDataInterface
,
5337 dxgi_factory_GetPrivateData
,
5338 dxgi_factory_GetParent
,
5339 dxgi_factory_EnumAdapters
,
5340 dxgi_factory_MakeWindowAssociation
,
5341 dxgi_factory_GetWindowAssociation
,
5342 dxgi_factory_CreateSwapChain
,
5343 dxgi_factory_CreateSoftwareAdapter
,
5348 IDXGIAdapter IDXGIAdapter_iface
;
5349 IDXGIAdapter
*wrapped_iface
;
5350 struct dxgi_factory factory
;
5351 unsigned int wrapped_output_count
;
5354 static inline struct dxgi_adapter
*impl_from_IDXGIAdapter(IDXGIAdapter
*iface
)
5356 return CONTAINING_RECORD(iface
, struct dxgi_adapter
, IDXGIAdapter_iface
);
5359 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_QueryInterface(IDXGIAdapter
*iface
, REFIID iid
, void **out
)
5361 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5363 if (IsEqualGUID(iid
, &IID_IDXGIAdapter
)
5364 || IsEqualGUID(iid
, &IID_IDXGIObject
)
5365 || IsEqualGUID(iid
, &IID_IUnknown
))
5367 IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5371 return IDXGIAdapter_QueryInterface(adapter
->wrapped_iface
, iid
, out
);
5374 static ULONG STDMETHODCALLTYPE
dxgi_adapter_AddRef(IDXGIAdapter
*iface
)
5376 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5377 return IDXGIAdapter_AddRef(adapter
->wrapped_iface
);
5380 static ULONG STDMETHODCALLTYPE
dxgi_adapter_Release(IDXGIAdapter
*iface
)
5382 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5383 return IDXGIAdapter_Release(adapter
->wrapped_iface
);
5386 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateData(IDXGIAdapter
*iface
,
5387 REFGUID guid
, UINT data_size
, const void *data
)
5389 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5390 return IDXGIAdapter_SetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5393 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_SetPrivateDataInterface(IDXGIAdapter
*iface
,
5394 REFGUID guid
, const IUnknown
*object
)
5396 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5397 return IDXGIAdapter_SetPrivateDataInterface(adapter
->wrapped_iface
, guid
, object
);
5400 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetPrivateData(IDXGIAdapter
*iface
,
5401 REFGUID guid
, UINT
*data_size
, void *data
)
5403 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5404 return IDXGIAdapter_GetPrivateData(adapter
->wrapped_iface
, guid
, data_size
, data
);
5407 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetParent(IDXGIAdapter
*iface
, REFIID iid
, void **parent
)
5409 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5410 return IDXGIFactory_QueryInterface(&adapter
->factory
.IDXGIFactory_iface
, iid
, parent
);
5413 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_EnumOutputs(IDXGIAdapter
*iface
,
5414 UINT output_idx
, IDXGIOutput
**output
)
5416 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5419 if (SUCCEEDED(hr
= IDXGIAdapter_EnumOutputs(adapter
->wrapped_iface
, output_idx
, output
)))
5420 ++adapter
->wrapped_output_count
;
5424 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_GetDesc(IDXGIAdapter
*iface
, DXGI_ADAPTER_DESC
*desc
)
5426 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5427 return IDXGIAdapter_GetDesc(adapter
->wrapped_iface
, desc
);
5430 static HRESULT STDMETHODCALLTYPE
dxgi_adapter_CheckInterfaceSupport(IDXGIAdapter
*iface
,
5431 REFGUID guid
, LARGE_INTEGER
*umd_version
)
5433 struct dxgi_adapter
*adapter
= impl_from_IDXGIAdapter(iface
);
5434 return IDXGIAdapter_CheckInterfaceSupport(adapter
->wrapped_iface
, guid
, umd_version
);
5437 static const struct IDXGIAdapterVtbl dxgi_adapter_vtbl
=
5439 dxgi_adapter_QueryInterface
,
5440 dxgi_adapter_AddRef
,
5441 dxgi_adapter_Release
,
5442 dxgi_adapter_SetPrivateData
,
5443 dxgi_adapter_SetPrivateDataInterface
,
5444 dxgi_adapter_GetPrivateData
,
5445 dxgi_adapter_GetParent
,
5446 dxgi_adapter_EnumOutputs
,
5447 dxgi_adapter_GetDesc
,
5448 dxgi_adapter_CheckInterfaceSupport
,
5451 static void test_object_wrapping(void)
5453 struct dxgi_adapter wrapper
;
5454 DXGI_ADAPTER_DESC desc
;
5455 IDXGIAdapter
*adapter
;
5456 IDXGIFactory
*factory
;
5457 ID3D10Device1
*device
;
5461 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
);
5462 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5464 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5465 if (hr
== DXGI_ERROR_NOT_FOUND
)
5467 skip("Could not enumerate adapters.\n");
5468 IDXGIFactory_Release(factory
);
5471 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5473 wrapper
.IDXGIAdapter_iface
.lpVtbl
= &dxgi_adapter_vtbl
;
5474 wrapper
.wrapped_iface
= adapter
;
5475 wrapper
.factory
.IDXGIFactory_iface
.lpVtbl
= &dxgi_factory_vtbl
;
5476 wrapper
.factory
.wrapped_iface
= factory
;
5477 wrapper
.factory
.wrapped_adapter_count
= 0;
5478 wrapper
.wrapped_output_count
= 0;
5480 hr
= D3D10CreateDevice1(&wrapper
.IDXGIAdapter_iface
, D3D10_DRIVER_TYPE_HARDWARE
, NULL
,
5481 0, D3D10_FEATURE_LEVEL_10_0
, D3D10_1_SDK_VERSION
, &device
);
5484 refcount
= ID3D10Device1_Release(device
);
5485 ok(!refcount
, "Device has %lu references left.\n", refcount
);
5488 hr
= IDXGIAdapter_GetDesc(&wrapper
.IDXGIAdapter_iface
, &desc
);
5489 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5490 ok(!wrapper
.factory
.wrapped_adapter_count
, "Got unexpected wrapped adapter count %u.\n",
5491 wrapper
.factory
.wrapped_adapter_count
);
5492 ok(!wrapper
.wrapped_output_count
, "Got unexpected wrapped output count %u.\n", wrapper
.wrapped_output_count
);
5494 refcount
= IDXGIAdapter_Release(&wrapper
.IDXGIAdapter_iface
);
5495 ok(!refcount
, "Adapter has %lu references left.\n", refcount
);
5496 refcount
= IDXGIFactory_Release(factory
);
5497 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
5506 static BOOL CALLBACK
enum_monitor_proc(HMONITOR monitor
, HDC dc
, RECT
*rect
, LPARAM lparam
)
5508 struct adapter_info
*adapter_info
= (struct adapter_info
*)lparam
;
5509 MONITORINFOEXW monitor_info
;
5511 monitor_info
.cbSize
= sizeof(monitor_info
);
5512 if (GetMonitorInfoW(monitor
, (MONITORINFO
*)&monitor_info
)
5513 && !lstrcmpiW(adapter_info
->name
, monitor_info
.szDevice
))
5515 adapter_info
->monitor
= monitor
;
5522 static HMONITOR
get_monitor(const WCHAR
*adapter_name
)
5524 struct adapter_info info
= {adapter_name
, NULL
};
5526 EnumDisplayMonitors(NULL
, NULL
, enum_monitor_proc
, (LPARAM
)&info
);
5527 return info
.monitor
;
5530 static void test_multi_adapter(void)
5532 unsigned int output_count
= 0, expected_output_count
= 0;
5533 unsigned int adapter_index
, output_index
, device_index
;
5534 DXGI_OUTPUT_DESC old_output_desc
, output_desc
;
5535 DXGI_ADAPTER_DESC1 adapter_desc1
;
5536 DXGI_ADAPTER_DESC adapter_desc
;
5537 DISPLAY_DEVICEW display_device
;
5538 MONITORINFO monitor_info
;
5539 DEVMODEW old_mode
, mode
;
5540 IDXGIAdapter1
*adapter1
;
5541 IDXGIFactory
*factory
;
5542 IDXGIAdapter
*adapter
;
5543 IDXGIOutput
*output
;
5549 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory
)))
5551 skip("Failed to create IDXGIFactory, hr %#lx.\n", hr
);
5555 hr
= IDXGIFactory_EnumAdapters(factory
, 0, NULL
);
5556 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
5558 hr
= IDXGIFactory_EnumAdapters(factory
, 0, &adapter
);
5559 if (hr
== DXGI_ERROR_NOT_FOUND
)
5561 skip("Could not enumerate adapters.\n");
5562 IDXGIFactory_Release(factory
);
5565 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5567 for (adapter_index
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_index
, &adapter
)); ++adapter_index
)
5569 for (output_index
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
)); ++output_index
)
5571 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5572 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5576 display_device
.cb
= sizeof(display_device
);
5577 for (device_index
= 0; EnumDisplayDevicesW(NULL
, device_index
, &display_device
, 0); ++device_index
)
5579 if (!lstrcmpiW(display_device
.DeviceName
, output_desc
.DeviceName
))
5585 ok(found
, "Adapter %u output %u: Failed to find device %s.\n",
5586 adapter_index
, output_index
, wine_dbgstr_w(output_desc
.DeviceName
));
5588 ok(display_device
.StateFlags
& DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
,
5589 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5590 output_index
, display_device
.StateFlags
);
5591 if (!adapter_index
&& !output_index
)
5592 ok(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
,
5593 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5594 output_index
, display_device
.StateFlags
);
5596 ok(!(display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
),
5597 "Adapter %u output %u: Got unexpected state flags %#lx.\n", adapter_index
,
5598 output_index
, display_device
.StateFlags
);
5600 /* Should have the same monitor handle. */
5601 monitor
= get_monitor(display_device
.DeviceName
);
5602 ok(!!monitor
, "Adapter %u output %u: Failed to find monitor %s.\n", adapter_index
,
5603 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5604 ok(monitor
== output_desc
.Monitor
,
5605 "Adapter %u output %u: Got unexpected monitor %p, expected %p.\n",
5606 adapter_index
, output_index
, monitor
, output_desc
.Monitor
);
5608 /* Should have the same monitor rectangle. */
5609 monitor_info
.cbSize
= sizeof(monitor_info
);
5610 ret
= GetMonitorInfoA(monitor
, &monitor_info
);
5611 ok(ret
, "Adapter %u output %u: Failed to get monitor info, error %#lx.\n", adapter_index
,
5612 output_index
, GetLastError());
5613 ok(EqualRect(&monitor_info
.rcMonitor
, &output_desc
.DesktopCoordinates
),
5614 "Adapter %u output %u: Got unexpected output rect %s, expected %s.\n",
5615 adapter_index
, output_index
, wine_dbgstr_rect(&monitor_info
.rcMonitor
),
5616 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5620 /* Test output description after it got detached */
5621 if (display_device
.StateFlags
& DISPLAY_DEVICE_PRIMARY_DEVICE
)
5623 IDXGIOutput_Release(output
);
5627 old_output_desc
= output_desc
;
5629 /* Save current display settings */
5630 memset(&old_mode
, 0, sizeof(old_mode
));
5631 old_mode
.dmSize
= sizeof(old_mode
);
5632 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &old_mode
);
5633 /* Win10 TestBots may return FALSE but it's actually successful */
5634 ok(ret
|| broken(!ret
),
5635 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#lx.\n",
5636 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5640 memset(&mode
, 0, sizeof(mode
));
5641 mode
.dmSize
= sizeof(mode
);
5642 mode
.dmFields
= DM_POSITION
| DM_PELSWIDTH
| DM_PELSHEIGHT
;
5643 mode
.dmPosition
= old_mode
.dmPosition
;
5644 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &mode
, NULL
,
5645 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5646 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5647 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5648 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5649 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5650 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5651 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5652 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5654 /* Check if it is really detached */
5655 memset(&mode
, 0, sizeof(mode
));
5656 mode
.dmSize
= sizeof(mode
);
5657 ret
= EnumDisplaySettingsW(display_device
.DeviceName
, ENUM_CURRENT_SETTINGS
, &mode
);
5658 /* Win10 TestBots may return FALSE but it's actually successful */
5659 ok(ret
|| broken(!ret
) ,
5660 "Adapter %u output %u: EnumDisplaySettingsW failed for %s, error %#lx.\n",
5661 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5663 if (mode
.dmPelsWidth
&& mode
.dmPelsHeight
)
5665 skip("Adapter %u output %u: Failed to detach device %s.\n", adapter_index
,
5666 output_index
, wine_dbgstr_w(display_device
.DeviceName
));
5667 IDXGIOutput_Release(output
);
5671 /* Only the AttachedToDesktop field is updated after an output is detached.
5672 * IDXGIAdapter_EnumOutputs() has to be called again to get other fields updated.
5673 * But resolution changes are reflected right away. This weird behaviour is currently
5674 * unimplemented in Wine */
5675 memset(&output_desc
, 0, sizeof(output_desc
));
5676 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5677 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5679 ok(!lstrcmpiW(output_desc
.DeviceName
, old_output_desc
.DeviceName
),
5680 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5681 output_index
, wine_dbgstr_w(old_output_desc
.DeviceName
),
5682 wine_dbgstr_w(output_desc
.DeviceName
));
5684 ok(EqualRect(&output_desc
.DesktopCoordinates
, &old_output_desc
.DesktopCoordinates
),
5685 "Adapter %u output %u: Expect desktop coordinates %s, got %s.\n",
5686 adapter_index
, output_index
,
5687 wine_dbgstr_rect(&old_output_desc
.DesktopCoordinates
),
5688 wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5689 ok(!output_desc
.AttachedToDesktop
,
5690 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5692 ok(output_desc
.Rotation
== old_output_desc
.Rotation
,
5693 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5694 output_index
, old_output_desc
.Rotation
, output_desc
.Rotation
);
5696 ok(output_desc
.Monitor
== old_output_desc
.Monitor
,
5697 "Adapter %u output %u: Expect monitor %p, got %p.\n", adapter_index
,
5698 output_index
, old_output_desc
.Monitor
, output_desc
.Monitor
);
5699 IDXGIOutput_Release(output
);
5701 /* Call IDXGIAdapter_EnumOutputs() again to get up-to-date output description */
5702 hr
= IDXGIAdapter_EnumOutputs(adapter
, output_index
, &output
);
5703 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5705 memset(&output_desc
, 0, sizeof(output_desc
));
5706 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
5707 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_index
,
5709 ok(!lstrcmpiW(output_desc
.DeviceName
, display_device
.DeviceName
),
5710 "Adapter %u output %u: Expect device name %s, got %s.\n", adapter_index
,
5711 output_index
, wine_dbgstr_w(display_device
.DeviceName
),
5712 wine_dbgstr_w(output_desc
.DeviceName
));
5713 ok(IsRectEmpty(&output_desc
.DesktopCoordinates
),
5714 "Adapter %u output %u: Expect desktop rect empty, got %s.\n", adapter_index
,
5715 output_index
, wine_dbgstr_rect(&output_desc
.DesktopCoordinates
));
5716 ok(!output_desc
.AttachedToDesktop
,
5717 "Adapter %u output %u: Expect output not attached to desktop.\n", adapter_index
,
5719 ok(output_desc
.Rotation
== DXGI_MODE_ROTATION_IDENTITY
,
5720 "Adapter %u output %u: Expect rotation %#x, got %#x.\n", adapter_index
,
5721 output_index
, DXGI_MODE_ROTATION_IDENTITY
, output_desc
.Rotation
);
5722 ok(!output_desc
.Monitor
, "Adapter %u output %u: Expect monitor NULL.\n", adapter_index
,
5725 /* Restore settings */
5726 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, &old_mode
, NULL
,
5727 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
5728 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5729 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5730 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5731 ret
= ChangeDisplaySettingsExW(display_device
.DeviceName
, NULL
, NULL
, 0, NULL
);
5732 ok(ret
== DISP_CHANGE_SUCCESSFUL
,
5733 "Adapter %u output %u: ChangeDisplaySettingsExW %s returned unexpected %ld.\n",
5734 adapter_index
, output_index
, wine_dbgstr_w(display_device
.DeviceName
), ret
);
5736 IDXGIOutput_Release(output
);
5739 IDXGIAdapter_Release(adapter
);
5742 /* Windows 8+ always have a WARP adapter present at the end. */
5743 todo_wine
ok(adapter_index
>= 2 || broken(adapter_index
< 2) /* Windows 7 and before */,
5744 "Got unexpected adapter count %u.\n", adapter_index
);
5745 if (adapter_index
< 2)
5747 todo_wine
win_skip("WARP adapter missing, skipping tests.\n");
5751 hr
= IDXGIFactory_EnumAdapters(factory
, adapter_index
- 1, &adapter
);
5752 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5753 hr
= IDXGIAdapter_GetDesc(adapter
, &adapter_desc
);
5754 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5755 todo_wine
ok(!lstrcmpW(adapter_desc
.Description
, L
"Microsoft Basic Render Driver"),
5756 "Got unexpected description %s.\n", wine_dbgstr_w(adapter_desc
.Description
));
5757 todo_wine
ok(adapter_desc
.VendorId
== 0x1414,
5758 "Got unexpected vendor ID %#x.\n", adapter_desc
.VendorId
);
5759 todo_wine
ok(adapter_desc
.DeviceId
== 0x008c,
5760 "Got unexpected device ID %#x.\n", adapter_desc
.DeviceId
);
5761 ok(adapter_desc
.SubSysId
== 0x0000,
5762 "Got unexpected sub-system ID %#x.\n", adapter_desc
.SubSysId
);
5763 ok(adapter_desc
.Revision
== 0x0000,
5764 "Got unexpected revision %#x.\n", adapter_desc
.Revision
);
5765 todo_wine
ok(!adapter_desc
.DedicatedVideoMemory
,
5766 "Got unexpected DedicatedVideoMemory %#Ix.\n", adapter_desc
.DedicatedVideoMemory
);
5767 ok(!adapter_desc
.DedicatedSystemMemory
,
5768 "Got unexpected DedicatedSystemMemory %#Ix.\n", adapter_desc
.DedicatedSystemMemory
);
5770 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter1
, (void **)&adapter1
);
5771 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
), "Got unexpected hr %#lx.\n", hr
);
5774 hr
= IDXGIAdapter1_GetDesc1(adapter1
, &adapter_desc1
);
5775 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5776 todo_wine
ok(adapter_desc1
.Flags
== DXGI_ADAPTER_FLAG_SOFTWARE
,
5777 "Got unexpected flags %#x.\n", adapter_desc1
.Flags
);
5778 IDXGIAdapter1_Release(adapter1
);
5781 IDXGIAdapter_Release(adapter
);
5784 IDXGIFactory_Release(factory
);
5786 expected_output_count
= GetSystemMetrics(SM_CMONITORS
);
5787 ok(output_count
== expected_output_count
, "Expect output count %d, got %d\n",
5788 expected_output_count
, output_count
);
5793 unsigned int message
;
5795 WPARAM expect_wparam
;
5798 static BOOL expect_no_messages
;
5799 static const struct message
*expect_messages
;
5800 static const struct message
*expect_messages_broken
;
5802 static BOOL
check_message(const struct message
*expected
,
5803 HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5805 if (expected
->message
!= message
)
5808 if (expected
->check_wparam
)
5810 ok(wparam
== expected
->expect_wparam
,
5811 "Got unexpected wparam %Ix for message %x, expected %Ix.\n",
5812 wparam
, message
, expected
->expect_wparam
);
5818 static LRESULT CALLBACK
test_wndproc(HWND hwnd
, unsigned int message
, WPARAM wparam
, LPARAM lparam
)
5820 ok(!expect_no_messages
, "Got unexpected message %#x, hwnd %p, wparam %#Ix, lparam %#Ix.\n",
5821 message
, hwnd
, wparam
, lparam
);
5823 if (expect_messages
)
5825 if (check_message(expect_messages
, hwnd
, message
, wparam
, lparam
))
5829 if (expect_messages_broken
)
5831 if (check_message(expect_messages_broken
, hwnd
, message
, wparam
, lparam
))
5832 ++expect_messages_broken
;
5835 return DefWindowProcA(hwnd
, message
, wparam
, lparam
);
5838 static void test_swapchain_window_messages(void)
5840 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
5841 IDXGISwapChain
*swapchain
;
5842 DXGI_MODE_DESC mode_desc
;
5843 IDXGIFactory
*factory
;
5844 IDXGIAdapter
*adapter
;
5845 IDXGIDevice
*device
;
5851 static const struct message enter_fullscreen_messages
[] =
5853 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5854 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5855 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5856 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5857 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5858 {WM_GETMINMAXINFO
, FALSE
, 0},
5859 {WM_NCCALCSIZE
, FALSE
, 0},
5860 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5861 {WM_MOVE
, FALSE
, 0},
5862 {WM_SIZE
, FALSE
, 0},
5865 static const struct message enter_fullscreen_messages_vista
[] =
5867 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5868 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5869 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5870 {WM_NCCALCSIZE
, FALSE
, 0},
5871 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5872 {WM_MOVE
, FALSE
, 0},
5873 {WM_SIZE
, FALSE
, 0},
5874 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5875 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5876 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5877 {WM_GETMINMAXINFO
, FALSE
, 0},
5878 {WM_NCCALCSIZE
, FALSE
, 0},
5879 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5880 {WM_SIZE
, FALSE
, 0},
5883 static const struct message leave_fullscreen_messages
[] =
5885 {WM_STYLECHANGING
, TRUE
, GWL_STYLE
},
5886 {WM_STYLECHANGED
, TRUE
, GWL_STYLE
},
5887 {WM_STYLECHANGING
, TRUE
, GWL_EXSTYLE
},
5888 {WM_STYLECHANGED
, TRUE
, GWL_EXSTYLE
},
5889 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5890 {WM_GETMINMAXINFO
, FALSE
, 0},
5891 {WM_NCCALCSIZE
, FALSE
, 0},
5892 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5893 {WM_MOVE
, FALSE
, 0},
5894 {WM_SIZE
, FALSE
, 0},
5897 static const struct message resize_target_messages
[] =
5899 {WM_WINDOWPOSCHANGING
, FALSE
, 0},
5900 {WM_GETMINMAXINFO
, FALSE
, 0},
5901 {WM_NCCALCSIZE
, FALSE
, 0},
5902 {WM_WINDOWPOSCHANGED
, FALSE
, 0},
5903 {WM_SIZE
, FALSE
, 0},
5907 if (!(device
= create_device(0)))
5909 skip("Failed to create device.\n");
5913 memset(&wc
, 0, sizeof(wc
));
5914 wc
.lpfnWndProc
= test_wndproc
;
5915 wc
.lpszClassName
= "dxgi_test_wndproc_wc";
5916 ok(RegisterClassA(&wc
), "Failed to register window class.\n");
5917 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
5918 ok(!!window
, "Failed to create window.\n");
5920 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
5921 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5922 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
5923 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5924 IDXGIAdapter_Release(adapter
);
5926 swapchain_desc
.BufferDesc
.Width
= 800;
5927 swapchain_desc
.BufferDesc
.Height
= 600;
5928 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
5929 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
5930 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
5931 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
5932 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
5933 swapchain_desc
.SampleDesc
.Count
= 1;
5934 swapchain_desc
.SampleDesc
.Quality
= 0;
5935 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
5936 swapchain_desc
.BufferCount
= 1;
5937 swapchain_desc
.OutputWindow
= window
;
5938 swapchain_desc
.Windowed
= TRUE
;
5939 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
5940 swapchain_desc
.Flags
= 0;
5942 /* create swapchain */
5944 expect_no_messages
= TRUE
;
5945 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
5946 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5948 expect_no_messages
= FALSE
;
5951 expect_messages
= resize_target_messages
;
5952 memset(&mode_desc
, 0, sizeof(mode_desc
));
5953 mode_desc
.Width
= 800;
5954 mode_desc
.Height
= 600;
5955 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5956 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5958 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5960 expect_messages
= resize_target_messages
;
5961 memset(&mode_desc
, 0, sizeof(mode_desc
));
5962 mode_desc
.Width
= 400;
5963 mode_desc
.Height
= 200;
5964 hr
= IDXGISwapChain_ResizeTarget(swapchain
, &mode_desc
);
5965 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5967 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5969 /* enter fullscreen */
5970 expect_messages
= enter_fullscreen_messages
;
5971 expect_messages_broken
= enter_fullscreen_messages_vista
;
5972 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
5973 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
5974 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
5975 "Got unexpected hr %#lx.\n", hr
);
5978 skip("Could not change fullscreen state.\n");
5983 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
5984 "Expected message %#x or %#x.\n",
5985 expect_messages
->message
, expect_messages_broken
->message
);
5986 expect_messages_broken
= NULL
;
5988 /* leave fullscreen */
5989 expect_messages
= leave_fullscreen_messages
;
5990 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
5991 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
5993 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
5994 expect_messages
= NULL
;
5996 refcount
= IDXGISwapChain_Release(swapchain
);
5997 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
5999 /* create fullscreen swapchain */
6000 DestroyWindow(window
);
6001 window
= CreateWindowA("dxgi_test_wndproc_wc", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6002 ok(!!window
, "Failed to create window.\n");
6003 swapchain_desc
.OutputWindow
= window
;
6004 swapchain_desc
.Windowed
= FALSE
;
6005 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6008 expect_messages
= enter_fullscreen_messages
;
6009 expect_messages_broken
= enter_fullscreen_messages_vista
;
6010 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6011 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6014 ok(!expect_messages
->message
|| broken(!expect_messages_broken
->message
),
6015 "Expected message %#x or %#x.\n",
6016 expect_messages
->message
, expect_messages_broken
->message
);
6017 expect_messages_broken
= NULL
;
6019 /* leave fullscreen */
6020 expect_messages
= leave_fullscreen_messages
;
6021 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6022 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6024 ok(!expect_messages
->message
, "Expected message %#x.\n", expect_messages
->message
);
6025 expect_messages
= NULL
;
6028 refcount
= IDXGISwapChain_Release(swapchain
);
6029 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6030 DestroyWindow(window
);
6032 refcount
= IDXGIDevice_Release(device
);
6033 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6034 refcount
= IDXGIFactory_Release(factory
);
6035 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6037 UnregisterClassA("dxgi_test_wndproc_wc", GetModuleHandleA(NULL
));
6040 static void test_swapchain_window_styles(void)
6042 LONG style
, exstyle
, fullscreen_style
, fullscreen_exstyle
;
6043 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6044 IDXGISwapChain
*swapchain
;
6045 IDXGIFactory
*factory
;
6046 IDXGIAdapter
*adapter
;
6047 IDXGIDevice
*device
;
6054 LONG style
, exstyle
;
6055 LONG expected_style
, expected_exstyle
;
6059 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
, 0,
6060 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
,
6062 {WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
, 0,
6063 WS_CAPTION
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_CLIPSIBLINGS
| WS_VISIBLE
,
6065 {WS_OVERLAPPED
| WS_VISIBLE
, 0,
6066 WS_OVERLAPPED
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6067 {WS_OVERLAPPED
| WS_MAXIMIZE
, 0,
6068 WS_OVERLAPPED
| WS_MAXIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6069 {WS_OVERLAPPED
| WS_MINIMIZE
, 0,
6070 WS_OVERLAPPED
| WS_MINIMIZE
| WS_CLIPSIBLINGS
| WS_CAPTION
, WS_EX_WINDOWEDGE
},
6071 {WS_CAPTION
| WS_DISABLED
, WS_EX_TOPMOST
,
6072 WS_CAPTION
| WS_DISABLED
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6073 {WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
, WS_EX_TOPMOST
,
6074 WS_CAPTION
| WS_DISABLED
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_TOPMOST
| WS_EX_WINDOWEDGE
},
6075 {WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
, WS_EX_APPWINDOW
,
6076 WS_CAPTION
| WS_SYSMENU
| WS_VISIBLE
| WS_CLIPSIBLINGS
, WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE
},
6077 {WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6078 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6080 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_BORDER
| WS_DLGFRAME
6081 | WS_VSCROLL
| WS_HSCROLL
| WS_SYSMENU
| WS_THICKFRAME
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
,
6085 if (!(device
= create_device(0)))
6087 skip("Failed to create device.\n");
6091 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6092 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6093 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6094 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6095 IDXGIAdapter_Release(adapter
);
6097 swapchain_desc
.BufferDesc
.Width
= 800;
6098 swapchain_desc
.BufferDesc
.Height
= 600;
6099 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6100 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6101 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6102 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6103 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6104 swapchain_desc
.SampleDesc
.Count
= 1;
6105 swapchain_desc
.SampleDesc
.Quality
= 0;
6106 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6107 swapchain_desc
.BufferCount
= 1;
6108 swapchain_desc
.Windowed
= TRUE
;
6109 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6110 swapchain_desc
.Flags
= 0;
6112 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6114 winetest_push_context("Test %u", i
);
6116 swapchain_desc
.OutputWindow
= CreateWindowExA(tests
[i
].exstyle
, "static", "dxgi_test",
6117 tests
[i
].style
, 0, 0, 400, 200, 0, 0, 0, 0);
6119 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6120 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6121 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6122 style
, tests
[i
].expected_style
);
6123 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6124 exstyle
, tests
[i
].expected_exstyle
);
6126 fullscreen_style
= tests
[i
].expected_style
& ~(WS_POPUP
| WS_MAXIMIZEBOX
6127 | WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_SYSMENU
| WS_DLGFRAME
| WS_BORDER
);
6128 fullscreen_exstyle
= tests
[i
].expected_exstyle
& ~(WS_EX_DLGMODALFRAME
6129 | WS_EX_TOOLWINDOW
| WS_EX_WINDOWEDGE
| WS_EX_CLIENTEDGE
| WS_EX_CONTEXTHELP
);
6130 fullscreen_exstyle
|= WS_EX_TOPMOST
;
6132 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6133 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6135 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6136 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6137 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6138 style
, tests
[i
].expected_style
);
6139 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6140 exstyle
, tests
[i
].expected_exstyle
);
6142 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6143 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6144 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6145 "Got unexpected hr %#lx.\n", hr
);
6148 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6149 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6150 todo_wine
ok(style
== fullscreen_style
, "Got unexpected style %#lx, expected %#lx.\n",
6151 style
, fullscreen_style
);
6152 ok(exstyle
== fullscreen_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6153 exstyle
, fullscreen_exstyle
);
6155 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6156 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6160 skip("Could not change fullscreen state.\n");
6163 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6164 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6165 ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6166 style
, tests
[i
].expected_style
);
6167 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6168 exstyle
, tests
[i
].expected_exstyle
);
6170 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6171 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6172 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6173 "Got unexpected hr %#lx.\n", hr
);
6176 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6177 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6178 todo_wine
ok(style
== fullscreen_style
, "Got unexpected style %#lx, expected %#lx.\n",
6179 style
, fullscreen_style
);
6180 ok(exstyle
== fullscreen_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6181 exstyle
, fullscreen_exstyle
);
6183 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_STYLE
, fullscreen_style
);
6184 SetWindowLongW(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
, fullscreen_exstyle
);
6186 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6187 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6189 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6190 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6191 todo_wine
ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6192 style
, tests
[i
].expected_style
);
6194 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6195 exstyle
, tests
[i
].expected_exstyle
);
6199 skip("Could not change fullscreen state.\n");
6202 refcount
= IDXGISwapChain_Release(swapchain
);
6203 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6205 style
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_STYLE
);
6206 exstyle
= GetWindowLongA(swapchain_desc
.OutputWindow
, GWL_EXSTYLE
);
6207 todo_wine
ok(style
== tests
[i
].expected_style
, "Got unexpected style %#lx, expected %#lx.\n",
6208 style
, tests
[i
].expected_style
);
6210 ok(exstyle
== tests
[i
].expected_exstyle
, "Got unexpected exstyle %#lx, expected %#lx.\n",
6211 exstyle
, tests
[i
].expected_exstyle
);
6213 DestroyWindow(swapchain_desc
.OutputWindow
);
6215 winetest_pop_context();
6218 refcount
= IDXGIDevice_Release(device
);
6219 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6220 refcount
= IDXGIFactory_Release(factory
);
6221 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6224 static void test_gamma_control(void)
6226 DXGI_GAMMA_CONTROL_CAPABILITIES caps
;
6227 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6228 IDXGISwapChain
*swapchain
;
6229 DXGI_GAMMA_CONTROL gamma
;
6230 IDXGIFactory
*factory
;
6231 IDXGIAdapter
*adapter
;
6232 IDXGIDevice
*device
;
6233 IDXGIOutput
*output
;
6238 if (!(device
= create_device(0)))
6240 skip("Failed to create device.\n");
6244 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
6245 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6247 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6248 if (hr
== DXGI_ERROR_NOT_FOUND
)
6250 skip("Adapter doesn't have any outputs.\n");
6251 IDXGIAdapter_Release(adapter
);
6252 IDXGIDevice_Release(device
);
6255 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6257 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6259 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6260 IDXGIOutput_Release(output
);
6262 swapchain_desc
.BufferDesc
.Width
= 640;
6263 swapchain_desc
.BufferDesc
.Height
= 480;
6264 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6265 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 60;
6266 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6267 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6268 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6269 swapchain_desc
.SampleDesc
.Count
= 1;
6270 swapchain_desc
.SampleDesc
.Quality
= 0;
6271 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6272 swapchain_desc
.BufferCount
= 1;
6273 swapchain_desc
.OutputWindow
= create_window();
6274 swapchain_desc
.Windowed
= TRUE
;
6275 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
6276 swapchain_desc
.Flags
= 0;
6278 hr
= IDXGIAdapter_GetParent(adapter
, &IID_IDXGIFactory
, (void **)&factory
);
6279 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6281 hr
= IDXGIFactory_CreateSwapChain(factory
, (IUnknown
*)device
, &swapchain_desc
, &swapchain
);
6282 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6283 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6284 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6285 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6286 "Got unexpected hr %#lx.\n", hr
);
6289 skip("Could not change fullscreen state.\n");
6293 hr
= IDXGISwapChain_GetContainingOutput(swapchain
, &output
);
6294 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6296 memset(&caps
, 0, sizeof(caps
));
6297 hr
= IDXGIOutput_GetGammaControlCapabilities(output
, &caps
);
6298 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6300 ok(caps
.MaxConvertedValue
> caps
.MinConvertedValue
6301 || broken(caps
.MaxConvertedValue
== 0.0f
&& caps
.MinConvertedValue
== 1.0f
) /* WARP */,
6302 "Expected max gamma value (%.8e) to be bigger than min value (%.8e).\n",
6303 caps
.MaxConvertedValue
, caps
.MinConvertedValue
);
6305 for (i
= 1; i
< caps
.NumGammaControlPoints
; ++i
)
6307 ok(caps
.ControlPointPositions
[i
] > caps
.ControlPointPositions
[i
- 1],
6308 "Expected control point positions to be strictly monotonically increasing (%.8e > %.8e).\n",
6309 caps
.ControlPointPositions
[i
], caps
.ControlPointPositions
[i
- 1]);
6312 memset(&gamma
, 0, sizeof(gamma
));
6313 hr
= IDXGIOutput_GetGammaControl(output
, &gamma
);
6315 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6316 hr
= IDXGIOutput_SetGammaControl(output
, &gamma
);
6317 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6319 IDXGIOutput_Release(output
);
6321 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6322 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6325 refcount
= IDXGISwapChain_Release(swapchain
);
6326 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6327 DestroyWindow(swapchain_desc
.OutputWindow
);
6329 IDXGIAdapter_Release(adapter
);
6330 refcount
= IDXGIDevice_Release(device
);
6331 ok(!refcount
, "Device has %lu references left.\n", refcount
);
6332 refcount
= IDXGIFactory_Release(factory
);
6333 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6336 static void test_window_association(IUnknown
*device
, BOOL is_d3d12
)
6338 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6339 LONG_PTR original_wndproc
, wndproc
;
6340 IDXGIFactory
*factory
, *factory2
;
6341 IDXGISwapChain
*swapchain
;
6342 IDXGIOutput
*output
;
6352 BOOL expect_fullscreen
;
6357 /* There are two reasons why VK_TAB and VK_ESC are not tested here:
6359 * - Posting them to the window doesn't exit fullscreen like
6360 * Alt+Enter does. Alt+Tab and Alt+Esc are handled somewhere else.
6361 * E.g., not calling IDXGISwapChain::Present() will break Alt+Tab
6362 * and Alt+Esc while Alt+Enter will still function.
6364 * - Posting them hangs the posting thread. Another thread that keeps
6365 * sending input is needed to avoid the hang. The hang is not
6366 * because of flush_events(). */
6369 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6370 {DXGI_MWA_NO_WINDOW_CHANGES
, FALSE
},
6371 {DXGI_MWA_NO_ALT_ENTER
, FALSE
, TRUE
},
6372 {DXGI_MWA_NO_ALT_ENTER
, FALSE
},
6373 {DXGI_MWA_NO_PRINT_SCREEN
, TRUE
},
6374 {DXGI_MWA_NO_PRINT_SCREEN
, FALSE
},
6379 swapchain_desc
.BufferDesc
.Width
= 640;
6380 swapchain_desc
.BufferDesc
.Height
= 480;
6381 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6382 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6383 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6384 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6385 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6386 swapchain_desc
.SampleDesc
.Count
= 1;
6387 swapchain_desc
.SampleDesc
.Quality
= 0;
6388 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6389 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6390 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6391 swapchain_desc
.Windowed
= TRUE
;
6392 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6393 swapchain_desc
.Flags
= 0;
6395 original_wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6397 hwnd2
= CreateWindowA("static", "dxgi_test2", 0, 0, 0, 400, 200, 0, 0, 0, 0);
6398 hr
= CreateDXGIFactory(&IID_IDXGIFactory
, (void **)&factory2
);
6399 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6401 get_factory(device
, is_d3d12
, &factory
);
6403 hr
= IDXGIFactory_GetWindowAssociation(factory
, NULL
);
6404 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6406 for (i
= 0; i
<= DXGI_MWA_VALID
; ++i
)
6408 hr
= IDXGIFactory_MakeWindowAssociation(factory
, NULL
, i
);
6409 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6411 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, i
);
6412 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6414 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6415 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix for flags %#x.\n",
6416 wndproc
, original_wndproc
, i
);
6418 hwnd
= (HWND
)0xdeadbeef;
6419 hr
= IDXGIFactory_GetWindowAssociation(factory
, &hwnd
);
6420 ok(hr
== S_OK
, "Got unexpected hr %#lx for flags %#x.\n", hr
, i
);
6421 /* Apparently GetWindowAssociation() always returns NULL, even when
6422 * MakeWindowAssociation() and GetWindowAssociation() are both
6423 * successfully called. */
6424 ok(!hwnd
, "Expect null associated window.\n");
6427 hr
= IDXGIFactory_MakeWindowAssociation(factory
, swapchain_desc
.OutputWindow
, DXGI_MWA_VALID
+ 1);
6428 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6430 /* Alt+Enter tests. */
6431 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6432 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6434 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6435 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix.\n", wndproc
, original_wndproc
);
6437 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6438 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6439 || broken(hr
== DXGI_ERROR_UNSUPPORTED
) /* Windows 7 testbot */,
6440 "Got unexpected hr %#lx.\n", hr
);
6443 skip("Could not change fullscreen state.\n");
6447 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6448 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6450 for (i
= 0; i
< ARRAY_SIZE(tests
); ++i
)
6452 winetest_push_context("Test %u", i
);
6454 /* First associate a window with the opposite flags. */
6455 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6456 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6458 /* Associate the current test window. */
6459 hwnd
= tests
[i
].flag
? swapchain_desc
.OutputWindow
: NULL
;
6460 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd
, tests
[i
].flag
);
6461 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6463 /* Associating a new test window doesn't override the old window. */
6464 hr
= IDXGIFactory_MakeWindowAssociation(factory
, hwnd2
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6465 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6467 /* Associations with a different factory don't affect the existing
6469 hr
= IDXGIFactory_MakeWindowAssociation(factory2
, hwnd
, ~tests
[i
].flag
& DXGI_MWA_VALID
);
6470 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6472 /* Post synthesized Alt + VK_RETURN WM_SYSKEYDOWN. */
6473 PostMessageA(swapchain_desc
.OutputWindow
, WM_SYSKEYDOWN
, VK_RETURN
,
6474 (MapVirtualKeyA(VK_RETURN
, MAPVK_VK_TO_VSC
) << 16) | 0x20000001);
6477 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, &output
);
6478 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6479 ok(fullscreen
== tests
[i
].expect_fullscreen
6480 || broken(tests
[i
].broken_d3d10
&& fullscreen
),
6481 "Got unexpected fullscreen %#x.\n", fullscreen
);
6482 ok(fullscreen
? !!output
: !output
, "Got unexpected output.\n");
6484 IDXGIOutput_Release(output
);
6486 wndproc
= GetWindowLongPtrW(swapchain_desc
.OutputWindow
, GWLP_WNDPROC
);
6487 ok(wndproc
== original_wndproc
, "Got unexpected wndproc %#Ix, expected %#Ix.\n",
6488 wndproc
, original_wndproc
);
6490 winetest_pop_context();
6494 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6495 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6497 refcount
= IDXGIFactory_Release(factory2
);
6498 ok(!refcount
, "Factory has %lu references left.\n", refcount
);
6499 DestroyWindow(hwnd2
);
6501 refcount
= IDXGISwapChain_Release(swapchain
);
6502 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6503 DestroyWindow(swapchain_desc
.OutputWindow
);
6505 refcount
= IDXGIFactory_Release(factory
);
6506 ok(refcount
== !is_d3d12
, "IDXGIFactory has %lu references left.\n", refcount
);
6509 static void test_output_ownership(IUnknown
*device
, BOOL is_d3d12
)
6511 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME open_adapter_gdi_desc
;
6512 D3DKMT_CHECKVIDPNEXCLUSIVEOWNERSHIP check_ownership_desc
;
6513 D3DKMT_CLOSEADAPTER close_adapter_desc
;
6514 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6515 DXGI_OUTPUT_DESC output_desc
;
6516 IDXGISwapChain
*swapchain
;
6517 IDXGIFactory
*factory
;
6518 IDXGIAdapter
*adapter
;
6519 IDXGIOutput
*output
;
6525 if (!pD3DKMTCheckVidPnExclusiveOwnership
6526 || pD3DKMTCheckVidPnExclusiveOwnership(NULL
) == STATUS_PROCEDURE_NOT_FOUND
)
6528 win_skip("D3DKMTCheckVidPnExclusiveOwnership() is unavailable.\n");
6532 get_factory(device
, is_d3d12
, &factory
);
6533 adapter
= get_adapter(device
, is_d3d12
);
6536 skip("Failed to get adapter on Direct3D %d.\n", is_d3d12
? 12 : 10);
6537 IDXGIFactory_Release(factory
);
6541 hr
= IDXGIAdapter_EnumOutputs(adapter
, 0, &output
);
6542 IDXGIAdapter_Release(adapter
);
6543 if (hr
== DXGI_ERROR_NOT_FOUND
)
6545 skip("Adapter doesn't have any outputs.\n");
6546 IDXGIFactory_Release(factory
);
6549 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6551 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6552 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6554 lstrcpyW(open_adapter_gdi_desc
.DeviceName
, output_desc
.DeviceName
);
6555 status
= pD3DKMTOpenAdapterFromGdiDisplayName(&open_adapter_gdi_desc
);
6556 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
6558 check_ownership_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6559 check_ownership_desc
.VidPnSourceId
= open_adapter_gdi_desc
.VidPnSourceId
;
6560 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6561 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6564 swapchain_desc
.BufferDesc
.Width
= 800;
6565 swapchain_desc
.BufferDesc
.Height
= 600;
6566 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
6567 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
6568 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6569 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
6570 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
6571 swapchain_desc
.SampleDesc
.Count
= 1;
6572 swapchain_desc
.SampleDesc
.Quality
= 0;
6573 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6574 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6575 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, NULL
, NULL
, NULL
, NULL
);
6576 swapchain_desc
.Windowed
= TRUE
;
6577 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6578 swapchain_desc
.Flags
= 0;
6579 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6580 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6582 /* Swapchain in fullscreen mode. */
6583 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, output
);
6584 /* DXGI_ERROR_NOT_CURRENTLY_AVAILABLE on some machines.
6585 * DXGI_ERROR_UNSUPPORTED on the Windows 7 testbot. */
6586 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== DXGI_ERROR_UNSUPPORTED
))
6588 skip("Failed to change fullscreen state.\n");
6591 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6593 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6594 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6595 ok(fullscreen
, "Got unexpected fullscreen state.\n");
6596 /* Win10 1909 doesn't seem to grab output exclusive ownership.
6597 * And all output ownership calls return S_OK on D3D10 and D3D12 with 1909. */
6600 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6601 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6606 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6607 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6608 todo_wine
ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6609 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6610 "Got unexpected status %#lx, expected %#lx.\n", status
,
6611 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6613 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, FALSE
);
6614 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6615 "Got unexpected hr %#lx.\n", hr
);
6616 hr
= IDXGIOutput_TakeOwnership(output
, NULL
, TRUE
);
6617 ok(hr
== DXGI_ERROR_INVALID_CALL
|| broken(hr
== S_OK
), /* Win10 1909 */
6618 "Got unexpected hr %#lx.\n", hr
);
6619 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6621 todo_wine
ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6623 todo_wine
ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
), /* Win10 1909 */
6624 "Got unexpected hr %#lx.\n", hr
);
6625 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6626 ok(hr
== E_NOINTERFACE
|| hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6627 IDXGIOutput_ReleaseOwnership(output
);
6628 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6629 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6632 /* IDXGIOutput_TakeOwnership always returns E_NOINTERFACE for d3d12. Tests
6637 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6638 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6639 "Got unexpected hr %#lx.\n", hr
);
6640 IDXGIOutput_ReleaseOwnership(output
);
6642 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6643 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6644 /* Note that the "exclusive" parameter to IDXGIOutput_TakeOwnership()
6645 * seems to behave opposite to what's described by MSDN. */
6646 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6647 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6648 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
||
6649 broken(status
== STATUS_SUCCESS
), /* Win10 1909 */
6650 "Got unexpected status %#lx, expected %#lx.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6651 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6652 ok(hr
== E_INVALIDARG
|| broken(hr
== S_OK
) /* Win10 1909 */, "Got unexpected hr %#lx.\n", hr
);
6653 IDXGIOutput_ReleaseOwnership(output
);
6655 /* Swapchain in windowed mode. */
6656 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6657 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6659 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
6660 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6661 ok(!fullscreen
, "Unexpected fullscreen state.\n");
6662 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6663 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6666 hr
= IDXGIOutput_TakeOwnership(output
, device
, FALSE
);
6667 ok(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
|| broken(hr
== S_OK
), /* Win10 1909 */
6668 "Got unexpected hr %#lx.\n", hr
);
6670 hr
= IDXGIOutput_TakeOwnership(output
, device
, TRUE
);
6671 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6672 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
,
6673 STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6674 ok(status
== STATUS_GRAPHICS_PRESENT_OCCLUDED
|| broken(hr
== S_OK
), /* Win10 1909 */
6675 "Got unexpected status %#lx, expected %#lx.\n", status
, STATUS_GRAPHICS_PRESENT_OCCLUDED
);
6676 IDXGIOutput_ReleaseOwnership(output
);
6677 status
= get_expected_vidpn_exclusive_ownership(&check_ownership_desc
, STATUS_SUCCESS
);
6678 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx, expected %#lx.\n", status
,
6682 IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6683 wait_device_idle(device
);
6685 IDXGIOutput_Release(output
);
6686 IDXGISwapChain_Release(swapchain
);
6687 DestroyWindow(swapchain_desc
.OutputWindow
);
6688 refcount
= IDXGIFactory_Release(factory
);
6689 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
6691 close_adapter_desc
.hAdapter
= open_adapter_gdi_desc
.hAdapter
;
6692 status
= pD3DKMTCloseAdapter(&close_adapter_desc
);
6693 ok(status
== STATUS_SUCCESS
, "Got unexpected status %#lx.\n", status
);
6696 static void test_cursor_clipping(IUnknown
*device
, BOOL is_d3d12
)
6698 unsigned int adapter_idx
, output_idx
, mode_idx
, mode_count
;
6699 DXGI_SWAP_CHAIN_DESC swapchain_desc
;
6700 DXGI_OUTPUT_DESC output_desc
;
6701 IDXGIAdapter
*adapter
= NULL
;
6702 RECT virtual_rect
, clip_rect
;
6703 unsigned int width
, height
;
6704 IDXGISwapChain
*swapchain
;
6705 DXGI_MODE_DESC
*modes
;
6706 IDXGIFactory
*factory
;
6707 IDXGIOutput
*output
;
6712 get_factory(device
, is_d3d12
, &factory
);
6714 swapchain_desc
.SampleDesc
.Count
= 1;
6715 swapchain_desc
.SampleDesc
.Quality
= 0;
6716 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6717 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
6718 swapchain_desc
.Windowed
= TRUE
;
6719 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
6720 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
6722 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
));
6725 winetest_push_context("Adapter %u", adapter_idx
);
6727 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
));
6730 winetest_push_context("Output %u", output_idx
);
6732 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, NULL
);
6733 ok(hr
== S_OK
|| broken(hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
), /* Win 7 TestBots */
6734 "Got unexpected hr %#lx.\n", hr
);
6735 if (hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
)
6737 win_skip("GetDisplayModeList() not supported.\n");
6738 IDXGIOutput_Release(output
);
6739 winetest_pop_context();
6743 modes
= heap_calloc(mode_count
, sizeof(*modes
));
6744 hr
= IDXGIOutput_GetDisplayModeList(output
, DXGI_FORMAT_R8G8B8A8_UNORM
, 0, &mode_count
, modes
);
6745 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6747 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
6748 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6749 width
= output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
;
6750 height
= output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
;
6751 for (mode_idx
= 0; mode_idx
< mode_count
; ++mode_idx
)
6753 if (modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
)
6756 ok(modes
[mode_idx
].Width
!= width
&& modes
[mode_idx
].Height
!= height
,
6757 "Failed to find a different mode than %ux%u.\n", width
, height
);
6759 ret
= ClipCursor(NULL
);
6760 ok(ret
, "ClipCursor failed, error %#lx.\n", GetLastError());
6761 get_virtual_rect(&virtual_rect
);
6762 ret
= GetClipCursor(&clip_rect
);
6763 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6764 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6765 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6767 swapchain_desc
.BufferDesc
.Width
= modes
[mode_idx
].Width
;
6768 swapchain_desc
.BufferDesc
.Height
= modes
[mode_idx
].Height
;
6769 swapchain_desc
.BufferDesc
.RefreshRate
= modes
[mode_idx
].RefreshRate
;
6770 swapchain_desc
.BufferDesc
.Format
= modes
[mode_idx
].Format
;
6771 swapchain_desc
.BufferDesc
.ScanlineOrdering
= modes
[mode_idx
].ScanlineOrdering
;
6772 swapchain_desc
.BufferDesc
.Scaling
= modes
[mode_idx
].Scaling
;
6773 swapchain_desc
.OutputWindow
= create_window();
6775 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
6776 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6779 get_virtual_rect(&virtual_rect
);
6780 ret
= GetClipCursor(&clip_rect
);
6781 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6782 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6783 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6785 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
6786 ok(hr
== S_OK
|| hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
6787 || broken(hr
== DXGI_ERROR_UNSUPPORTED
), /* Win 7 testbot */
6788 "Got unexpected hr %#lx.\n", hr
);
6791 skip("Could not change fullscreen state, hr %#lx.\n", hr
);
6792 IDXGISwapChain_Release(swapchain
);
6793 IDXGIOutput_Release(output
);
6794 DestroyWindow(swapchain_desc
.OutputWindow
);
6795 winetest_pop_context();
6800 get_virtual_rect(&virtual_rect
);
6801 ret
= GetClipCursor(&clip_rect
);
6802 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6803 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6804 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6806 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
6807 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6808 refcount
= IDXGISwapChain_Release(swapchain
);
6809 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
6810 refcount
= IDXGIOutput_Release(output
);
6811 ok(!refcount
, "IDXGIOutput has %lu references left.\n", refcount
);
6812 DestroyWindow(swapchain_desc
.OutputWindow
);
6815 get_virtual_rect(&virtual_rect
);
6816 ret
= GetClipCursor(&clip_rect
);
6817 ok(ret
, "GetClipCursor failed, error %#lx.\n", GetLastError());
6818 ok(EqualRect(&clip_rect
, &virtual_rect
), "Expect clip rect %s, got %s.\n",
6819 wine_dbgstr_rect(&virtual_rect
), wine_dbgstr_rect(&clip_rect
));
6821 winetest_pop_context();
6824 IDXGIAdapter_Release(adapter
);
6826 winetest_pop_context();
6829 refcount
= IDXGIFactory_Release(factory
);
6830 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
6833 static void test_factory_check_feature_support(void)
6835 IDXGIFactory5
*factory
;
6840 if (FAILED(hr
= CreateDXGIFactory(&IID_IDXGIFactory5
, (void**)&factory
)))
6842 win_skip("IDXGIFactory5 is not available.\n");
6846 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, 0x12345678, (void *)&data
, sizeof(data
));
6847 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6849 /* Crashes on Windows. */
6852 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, NULL
, sizeof(data
));
6853 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6856 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) - 1);
6857 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6859 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
) + 1);
6860 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6862 data
= (BOOL
)0xdeadbeef;
6863 hr
= IDXGIFactory5_CheckFeatureSupport(factory
, DXGI_FEATURE_PRESENT_ALLOW_TEARING
, &data
, sizeof(data
));
6864 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6865 ok(data
== TRUE
|| data
== FALSE
, "Got unexpected data %#x.\n", data
);
6867 ref_count
= IDXGIFactory5_Release(factory
);
6868 ok(!ref_count
, "Factory has %lu references left.\n", ref_count
);
6871 static void test_frame_latency_event(IUnknown
*device
, BOOL is_d3d12
)
6873 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
6874 IDXGISwapChain2
*swapchain2
;
6875 IDXGISwapChain1
*swapchain1
;
6876 IDXGIFactory2
*factory2
;
6877 IDXGIFactory
*factory
;
6886 get_factory(device
, is_d3d12
, &factory
);
6888 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
6889 IDXGIFactory_Release(factory
);
6892 win_skip("IDXGIFactory2 not available.\n");
6896 window
= create_window();
6898 swapchain_desc
.Width
= 640;
6899 swapchain_desc
.Height
= 480;
6900 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
6901 swapchain_desc
.Stereo
= FALSE
;
6902 swapchain_desc
.SampleDesc
.Count
= 1;
6903 swapchain_desc
.SampleDesc
.Quality
= 0;
6904 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
6905 swapchain_desc
.BufferCount
= 2;
6906 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
6907 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
6908 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
6909 swapchain_desc
.Flags
= 0;
6911 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6912 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6913 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6915 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6916 IDXGISwapChain1_Release(swapchain1
);
6919 win_skip("IDXGISwapChain2 not available.\n");
6920 IDXGIFactory2_Release(factory2
);
6921 DestroyWindow(window
);
6925 /* test swap chain without waitable object */
6926 frame_latency
= 0xdeadbeef;
6927 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6928 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6929 ok(frame_latency
== 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency
);
6930 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 1);
6931 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6932 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6933 ok(!event
, "Got unexpected event %p.\n", event
);
6935 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6936 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
6938 /* test swap chain with waitable object */
6939 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT
;
6941 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
6942 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
6943 ok(hr
== S_OK
, "Failed to create swap chain, hr %#lx.\n", hr
);
6944 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain2
, (void**)&swapchain2
);
6945 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6946 IDXGISwapChain1_Release(swapchain1
);
6948 event
= IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2
);
6949 ok(!!event
, "Got unexpected event %p.\n", event
);
6951 /* auto-reset event */
6952 wait_result
= WaitForSingleObject(event
, 0);
6953 ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6954 wait_result
= WaitForSingleObject(event
, 0);
6955 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6957 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6958 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6959 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6961 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 0);
6962 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
6963 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6964 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6965 ok(frame_latency
== 1, "Got unexpected frame latency %#x.\n", frame_latency
);
6967 hr
= IDXGISwapChain2_SetMaximumFrameLatency(swapchain2
, 3);
6968 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6969 hr
= IDXGISwapChain2_GetMaximumFrameLatency(swapchain2
, &frame_latency
);
6970 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
6971 ok(frame_latency
== 3, "Got unexpected frame latency %#x.\n", frame_latency
);
6973 wait_result
= WaitForSingleObject(event
, 0);
6974 todo_wine
ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
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
, 100);
6978 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6980 for (i
= 0; i
< 5; i
++)
6982 hr
= IDXGISwapChain2_Present(swapchain2
, 0, 0);
6983 ok(hr
== S_OK
, "Present %u failed with hr %#lx.\n", i
, hr
);
6985 wait_result
= WaitForSingleObject(event
, 100);
6986 ok(!wait_result
, "Got unexpected wait result %#lx.\n", wait_result
);
6989 wait_result
= WaitForSingleObject(event
, 100);
6990 ok(wait_result
== WAIT_TIMEOUT
, "Got unexpected wait result %#lx.\n", wait_result
);
6992 ref_count
= IDXGISwapChain2_Release(swapchain2
);
6993 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
6994 DestroyWindow(window
);
6995 ref_count
= IDXGIFactory2_Release(factory2
);
6996 ok(ref_count
== !is_d3d12
, "Factory has %lu references left.\n", ref_count
);
6999 static void test_colour_space_support(IUnknown
*device
, BOOL is_d3d12
)
7001 DXGI_SWAP_CHAIN_DESC1 swapchain_desc
;
7002 IDXGISwapChain3
*swapchain3
;
7003 IDXGISwapChain1
*swapchain1
;
7004 IDXGIFactory2
*factory2
;
7005 IDXGIFactory
*factory
;
7012 static const DXGI_COLOR_SPACE_TYPE colour_spaces
[] =
7014 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
,
7015 DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709
,
7016 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P709
,
7017 DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020
,
7018 DXGI_COLOR_SPACE_RESERVED
,
7019 DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601
,
7020 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601
,
7021 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601
,
7022 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709
,
7023 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709
,
7024 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020
,
7025 DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020
,
7026 DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
,
7027 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020
,
7028 DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020
,
7029 DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_TOPLEFT_P2020
,
7030 DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_TOPLEFT_P2020
,
7031 DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020
,
7032 DXGI_COLOR_SPACE_YCBCR_STUDIO_GHLG_TOPLEFT_P2020
,
7033 DXGI_COLOR_SPACE_YCBCR_FULL_GHLG_TOPLEFT_P2020
,
7036 get_factory(device
, is_d3d12
, &factory
);
7038 hr
= IDXGIFactory_QueryInterface(factory
, &IID_IDXGIFactory2
, (void**)&factory2
);
7039 IDXGIFactory_Release(factory
);
7042 win_skip("IDXGIFactory2 not available.\n");
7046 window
= create_window();
7048 swapchain_desc
.Width
= 640;
7049 swapchain_desc
.Height
= 480;
7050 swapchain_desc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7051 swapchain_desc
.Stereo
= FALSE
;
7052 swapchain_desc
.SampleDesc
.Count
= 1;
7053 swapchain_desc
.SampleDesc
.Quality
= 0;
7054 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7055 swapchain_desc
.BufferCount
= 2;
7056 swapchain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
7057 swapchain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_FLIP_DISCARD
;
7058 swapchain_desc
.AlphaMode
= DXGI_ALPHA_MODE_UNSPECIFIED
;
7059 swapchain_desc
.Flags
= 0;
7061 hr
= IDXGIFactory2_CreateSwapChainForHwnd(factory2
, device
,
7062 window
, &swapchain_desc
, NULL
, NULL
, &swapchain1
);
7063 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7065 hr
= IDXGISwapChain1_QueryInterface(swapchain1
, &IID_IDXGISwapChain3
, (void**)&swapchain3
);
7066 IDXGISwapChain1_Release(swapchain1
);
7069 win_skip("IDXGISwapChain3 not available.\n");
7070 IDXGIFactory2_Release(factory2
);
7071 DestroyWindow(window
);
7075 for (i
= 0; i
< ARRAY_SIZE(colour_spaces
); ++i
)
7077 support
= 0xdeadbeef;
7078 hr
= IDXGISwapChain3_CheckColorSpaceSupport(swapchain3
, colour_spaces
[i
], &support
);
7079 ok(hr
== S_OK
, "Got unexpected hr %#lx for test %u.\n", hr
, i
);
7080 ok(!(support
& ~DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
),
7081 "Got unexpected support flags %#x for test %u.\n", support
, i
);
7083 if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709
)
7085 ok(support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
,
7086 "Required colour space not supported for test %u.\n", i
);
7088 else if (colour_spaces
[i
] == DXGI_COLOR_SPACE_RESERVED
)
7090 ok(!support
, "Invalid colour space supported for test %u.\n", i
);
7093 hr
= IDXGISwapChain3_SetColorSpace1(swapchain3
, colour_spaces
[i
]);
7094 ok(hr
== (support
& DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT
) ? S_OK
: E_INVALIDARG
,
7095 "Got unexpected hr %#lx for text %u.\n", hr
, i
);
7098 ref_count
= IDXGISwapChain3_Release(swapchain3
);
7099 ok(!ref_count
, "Swap chain has %lu references left.\n", ref_count
);
7100 DestroyWindow(window
);
7101 ref_count
= IDXGIFactory2_Release(factory2
);
7102 ok(ref_count
== !is_d3d12
, "Factory has %lu references left.\n", ref_count
);
7105 static void test_mode_change(IUnknown
*device
, BOOL is_d3d12
)
7107 unsigned int user32_width
= 0, user32_height
= 0, d3d_width
= 0, d3d_height
= 0;
7108 unsigned int display_count
= 0, mode_idx
= 0, adapter_idx
, output_idx
;
7109 DEVMODEW
*original_modes
= NULL
, old_devmode
, devmode
, devmode2
;
7110 DXGI_SWAP_CHAIN_DESC swapchain_desc
, swapchain_desc2
;
7111 IDXGIOutput
*output
, *second_output
= NULL
;
7112 WCHAR second_monitor_name
[CCHDEVICENAME
];
7113 IDXGISwapChain
*swapchain
, *swapchain2
;
7114 DXGI_OUTPUT_DESC output_desc
;
7115 IDXGIAdapter
*adapter
;
7116 IDXGIFactory
*factory
;
7117 BOOL fullscreen
, ret
;
7122 memset(&devmode
, 0, sizeof(devmode
));
7123 devmode
.dmSize
= sizeof(devmode
);
7124 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode
);
7125 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7126 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7127 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode
);
7128 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7129 ok(equal_mode_rect(&devmode
, ®istry_mode
), "Got a different mode.\n");
7131 while (EnumDisplaySettingsW(NULL
, mode_idx
++, &devmode
))
7133 if (devmode
.dmPelsWidth
== registry_mode
.dmPelsWidth
7134 && devmode
.dmPelsHeight
== registry_mode
.dmPelsHeight
)
7137 if (!d3d_width
&& !d3d_height
)
7139 d3d_width
= devmode
.dmPelsWidth
;
7140 d3d_height
= devmode
.dmPelsHeight
;
7144 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7147 user32_width
= devmode
.dmPelsWidth
;
7148 user32_height
= devmode
.dmPelsHeight
;
7151 if (!user32_width
|| !user32_height
)
7153 skip("Failed to find three different display modes for the primary output.\n");
7157 ret
= save_display_modes(&original_modes
, &display_count
);
7158 ok(ret
, "Failed to save original display modes.\n");
7160 get_factory(device
, is_d3d12
, &factory
);
7162 /* Test that no mode restorations if no mode changes actually happened */
7163 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7164 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7166 swapchain_desc
.BufferDesc
.Width
= registry_mode
.dmPelsWidth
;
7167 swapchain_desc
.BufferDesc
.Height
= registry_mode
.dmPelsHeight
;
7168 swapchain_desc
.BufferDesc
.RefreshRate
.Numerator
= 60;
7169 swapchain_desc
.BufferDesc
.RefreshRate
.Denominator
= 1;
7170 swapchain_desc
.BufferDesc
.Format
= DXGI_FORMAT_R8G8B8A8_UNORM
;
7171 swapchain_desc
.BufferDesc
.ScanlineOrdering
= DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED
;
7172 swapchain_desc
.BufferDesc
.Scaling
= DXGI_MODE_SCALING_UNSPECIFIED
;
7173 swapchain_desc
.SampleDesc
.Count
= 1;
7174 swapchain_desc
.SampleDesc
.Quality
= 0;
7175 swapchain_desc
.BufferUsage
= DXGI_USAGE_RENDER_TARGET_OUTPUT
;
7176 swapchain_desc
.BufferCount
= is_d3d12
? 2 : 1;
7177 swapchain_desc
.OutputWindow
= CreateWindowA("static", "dxgi_test", 0, 0, 0, 400, 200, 0, 0, 0, 0);
7178 swapchain_desc
.Windowed
= TRUE
;
7179 swapchain_desc
.SwapEffect
= is_d3d12
? DXGI_SWAP_EFFECT_FLIP_DISCARD
: DXGI_SWAP_EFFECT_DISCARD
;
7180 swapchain_desc
.Flags
= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
;
7182 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7183 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7184 refcount
= IDXGISwapChain_Release(swapchain
);
7185 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7187 memset(&devmode2
, 0, sizeof(devmode2
));
7188 devmode2
.dmSize
= sizeof(devmode2
);
7189 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7190 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7191 ok(equal_mode_rect(&devmode2
, ®istry_mode
), "Got a different mode.\n");
7192 ret
= restore_display_modes(original_modes
, display_count
);
7193 ok(ret
, "Failed to restore display modes.\n");
7195 /* If current display settings are different than the display settings in registry before
7196 * calling SetFullscreenState() */
7197 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7198 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7200 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7201 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7202 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7203 ok(hr
== DXGI_ERROR_UNSUPPORTED
/* Win7 */
7204 || hr
== S_OK
/* Win8~Win10 1909 */
7205 || hr
== DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
, /* Win10 2004 */
7206 "Got unexpected hr %#lx.\n", hr
);
7208 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7209 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7210 refcount
= IDXGISwapChain_Release(swapchain
);
7211 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7212 ret
= restore_display_modes(original_modes
, display_count
);
7213 ok(ret
, "Failed to restore display modes.\n");
7215 /* Test that mode restorations use display settings in the registry with a fullscreen device */
7216 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7217 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7218 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7221 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
7222 refcount
= IDXGISwapChain_Release(swapchain
);
7223 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7227 change_ret
= ChangeDisplaySettingsW(&devmode
, CDS_UPDATEREGISTRY
| CDS_NORESET
);
7228 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsW failed with %ld.\n", change_ret
);
7229 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7230 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7232 ret
= EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7233 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7234 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7235 ret
= EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7236 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7237 ok(equal_mode_rect(&devmode2
, &devmode
), "Got a different mode.\n");
7238 refcount
= IDXGISwapChain_Release(swapchain
);
7239 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7240 ret
= restore_display_modes(original_modes
, display_count
);
7241 ok(ret
, "Failed to restore display modes.\n");
7243 for (adapter_idx
= 0; SUCCEEDED(IDXGIFactory_EnumAdapters(factory
, adapter_idx
, &adapter
)); ++adapter_idx
)
7245 for (output_idx
= 0; SUCCEEDED(IDXGIAdapter_EnumOutputs(adapter
, output_idx
, &output
)); ++output_idx
)
7247 hr
= IDXGIOutput_GetDesc(output
, &output_desc
);
7248 ok(hr
== S_OK
, "Adapter %u output %u: Got unexpected hr %#lx.\n", adapter_idx
, output_idx
, hr
);
7250 if ((adapter_idx
|| output_idx
) && output_desc
.AttachedToDesktop
)
7252 second_output
= output
;
7256 IDXGIOutput_Release(output
);
7259 IDXGIAdapter_Release(adapter
);
7266 skip("Following tests require two monitors.\n");
7269 lstrcpyW(second_monitor_name
, output_desc
.DeviceName
);
7271 memset(&old_devmode
, 0, sizeof(old_devmode
));
7272 old_devmode
.dmSize
= sizeof(old_devmode
);
7273 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &old_devmode
);
7274 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7281 while (EnumDisplaySettingsW(second_monitor_name
, mode_idx
++, &devmode
))
7283 if (devmode
.dmPelsWidth
== old_devmode
.dmPelsWidth
7284 && devmode
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7287 if (!d3d_width
&& !d3d_height
)
7289 d3d_width
= devmode
.dmPelsWidth
;
7290 d3d_height
= devmode
.dmPelsHeight
;
7294 if (devmode
.dmPelsWidth
== d3d_width
&& devmode
.dmPelsHeight
== d3d_height
)
7297 user32_width
= devmode
.dmPelsWidth
;
7298 user32_height
= devmode
.dmPelsHeight
;
7301 if (!user32_width
|| !user32_height
)
7303 skip("Failed to find three different display modes for the second output.\n");
7307 /* Test that mode restorations for non-primary outputs upon fullscreen state changes */
7308 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7309 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7310 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7311 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7313 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
, CDS_RESET
, NULL
);
7314 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret
);
7315 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7316 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7317 if (devmode2
.dmPelsWidth
== old_devmode
.dmPelsWidth
7318 && devmode2
.dmPelsHeight
== old_devmode
.dmPelsHeight
)
7320 skip("Failed to change display settings of the second monitor.\n");
7321 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7322 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7323 refcount
= IDXGISwapChain_Release(swapchain
);
7324 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7328 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7329 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7331 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7332 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7333 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7334 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7335 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7336 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7337 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7338 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7339 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7340 old_devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", old_devmode
.dmPelsWidth
,
7341 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7342 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7343 old_devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", old_devmode
.dmPelsHeight
,
7344 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7346 refcount
= IDXGISwapChain_Release(swapchain
);
7347 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7348 ret
= restore_display_modes(original_modes
, display_count
);
7349 ok(ret
, "Failed to restore display modes.\n");
7351 /* Test that mode restorations for non-primary outputs use display settings in the registry */
7352 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7353 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7354 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7355 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7357 change_ret
= ChangeDisplaySettingsExW(second_monitor_name
, &devmode
, NULL
,
7358 CDS_UPDATEREGISTRY
| CDS_NORESET
, NULL
);
7359 ok(change_ret
== DISP_CHANGE_SUCCESSFUL
, "ChangeDisplaySettingsExW failed with %ld.\n", change_ret
);
7360 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7361 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7363 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7364 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7365 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7366 "Expected resolution %lux%lu, got %lux%lu.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7367 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7368 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7369 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7370 ok(devmode2
.dmPelsWidth
== devmode
.dmPelsWidth
&& devmode2
.dmPelsHeight
== devmode
.dmPelsHeight
,
7371 "Expected resolution %lux%lu, got %lux%lu.\n", devmode
.dmPelsWidth
, devmode
.dmPelsHeight
,
7372 devmode2
.dmPelsWidth
, devmode2
.dmPelsHeight
);
7373 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7374 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7375 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7376 devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", devmode
.dmPelsWidth
,
7377 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7378 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7379 devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", devmode
.dmPelsHeight
,
7380 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7382 refcount
= IDXGISwapChain_Release(swapchain
);
7383 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7384 ret
= restore_display_modes(original_modes
, display_count
);
7385 ok(ret
, "Failed to restore display modes.\n");
7387 /* Test that mode restorations for non-primary outputs on fullscreen state changes when there
7388 * are two fullscreen swapchains on different outputs */
7389 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc
, &swapchain
);
7390 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7392 swapchain_desc2
= swapchain_desc
;
7393 swapchain_desc
.BufferDesc
.Width
= d3d_width
;
7394 swapchain_desc
.BufferDesc
.Height
= d3d_height
;
7395 swapchain_desc2
.OutputWindow
= CreateWindowA("static", "dxgi_test2", 0,
7396 old_devmode
.dmPosition
.x
, old_devmode
.dmPosition
.y
, 400, 200, 0, 0, 0, 0);
7397 hr
= IDXGIFactory_CreateSwapChain(factory
, device
, &swapchain_desc2
, &swapchain2
);
7398 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7399 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, TRUE
, NULL
);
7400 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7401 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, TRUE
, NULL
);
7404 skip("SetFullscreenState failed, hr %#lx.\n", hr
);
7405 refcount
= IDXGISwapChain_Release(swapchain2
);
7406 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7407 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7408 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7409 refcount
= IDXGISwapChain_Release(swapchain
);
7410 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7414 hr
= IDXGISwapChain_SetFullscreenState(swapchain
, FALSE
, NULL
);
7415 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7416 hr
= IDXGISwapChain_GetFullscreenState(swapchain
, &fullscreen
, NULL
);
7417 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7418 ok(!fullscreen
, "Expected swapchain not fullscreen.\n");
7419 hr
= IDXGISwapChain_GetFullscreenState(swapchain2
, &fullscreen
, NULL
);
7420 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7421 ok(fullscreen
, "Expected swapchain fullscreen.\n");
7423 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_CURRENT_SETTINGS
, &devmode2
);
7424 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7425 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7426 ret
= EnumDisplaySettingsW(second_monitor_name
, ENUM_REGISTRY_SETTINGS
, &devmode2
);
7427 ok(ret
, "EnumDisplaySettingsW failed, error %#lx.\n", GetLastError());
7428 ok(equal_mode_rect(&devmode2
, &old_devmode
), "Got a different mode.\n");
7429 hr
= IDXGIOutput_GetDesc(second_output
, &output_desc
);
7430 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7431 ok(output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
==
7432 old_devmode
.dmPelsWidth
, "Expected width %lu, got %lu.\n", old_devmode
.dmPelsWidth
,
7433 output_desc
.DesktopCoordinates
.right
- output_desc
.DesktopCoordinates
.left
);
7434 ok(output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
==
7435 old_devmode
.dmPelsHeight
, "Expected height %lu, got %lu.\n", old_devmode
.dmPelsHeight
,
7436 output_desc
.DesktopCoordinates
.bottom
- output_desc
.DesktopCoordinates
.top
);
7438 hr
= IDXGISwapChain_SetFullscreenState(swapchain2
, FALSE
, NULL
);
7439 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7440 refcount
= IDXGISwapChain_Release(swapchain2
);
7441 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7442 refcount
= IDXGISwapChain_Release(swapchain
);
7443 ok(!refcount
, "IDXGISwapChain has %lu references left.\n", refcount
);
7444 DestroyWindow(swapchain_desc2
.OutputWindow
);
7445 ret
= restore_display_modes(original_modes
, display_count
);
7446 ok(ret
, "Failed to restore display modes.\n");
7450 IDXGIOutput_Release(second_output
);
7451 DestroyWindow(swapchain_desc
.OutputWindow
);
7452 refcount
= IDXGIFactory_Release(factory
);
7453 ok(refcount
== !is_d3d12
, "Got unexpected refcount %lu.\n", refcount
);
7454 ret
= restore_display_modes(original_modes
, display_count
);
7455 ok(ret
, "Failed to restore display modes.\n");
7456 heap_free(original_modes
);
7459 static void test_swapchain_present_count(IUnknown
*device
, BOOL is_d3d12
)
7461 UINT present_count
, expected
;
7462 IDXGISwapChain
*swapchain
;
7466 window
= create_window();
7467 swapchain
= create_swapchain(device
, is_d3d12
, window
);
7469 present_count
= ~0u;
7470 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7471 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7472 ok(!present_count
, "Got unexpected present count %u.\n", present_count
);
7474 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7475 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7476 expected
= present_count
+ 1;
7477 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7478 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7479 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7481 hr
= IDXGISwapChain_Present(swapchain
, 10, 0);
7482 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
7483 expected
= present_count
;
7484 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7485 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7486 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7488 hr
= IDXGISwapChain_Present(swapchain
, 0, DXGI_PRESENT_TEST
);
7489 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7490 expected
= present_count
;
7491 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7492 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7493 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7495 ShowWindow(window
, SW_MINIMIZE
);
7496 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7497 ok(hr
== (is_d3d12
? S_OK
: DXGI_STATUS_OCCLUDED
), "Got unexpected hr %#lx.\n", hr
);
7498 expected
= present_count
+ !!is_d3d12
;
7499 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7500 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7501 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7503 ShowWindow(window
, SW_NORMAL
);
7504 hr
= IDXGISwapChain_Present(swapchain
, 0, 0);
7505 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7506 expected
= present_count
+ 1;
7507 hr
= IDXGISwapChain_GetLastPresentCount(swapchain
, &present_count
);
7508 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7509 ok(present_count
== expected
, "Got unexpected present count %u, expected %u.\n", present_count
, expected
);
7511 IDXGISwapChain_Release(swapchain
);
7512 DestroyWindow(window
);
7515 static void test_video_memory_budget_notification(void)
7517 DXGI_QUERY_VIDEO_MEMORY_INFO memory_info
;
7518 IDXGIAdapter3
*adapter3
;
7519 IDXGIAdapter
*adapter
;
7520 IDXGIDevice
*device
;
7526 if (!(device
= create_device(0)))
7528 skip("Failed to create device.\n");
7532 hr
= IDXGIDevice_GetAdapter(device
, &adapter
);
7533 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7534 hr
= IDXGIAdapter_QueryInterface(adapter
, &IID_IDXGIAdapter3
, (void **)&adapter3
);
7535 ok(hr
== S_OK
|| hr
== E_NOINTERFACE
, "Got unexpected hr %#lx.\n", hr
);
7536 if (hr
== E_NOINTERFACE
)
7539 hr
= IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3
, NULL
, &cookie
);
7540 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
7542 event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
7543 hr
= IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3
, event
, NULL
);
7544 ok(hr
== DXGI_ERROR_INVALID_CALL
, "Got unexpected hr %#lx.\n", hr
);
7546 hr
= IDXGIAdapter3_RegisterVideoMemoryBudgetChangeNotificationEvent(adapter3
, event
, &cookie
);
7547 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7548 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_LOCAL
, &memory_info
);
7549 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7550 if (!memory_info
.Budget
)
7552 hr
= IDXGIAdapter3_QueryVideoMemoryInfo(adapter3
, 0, DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL
, &memory_info
);
7553 ok(hr
== S_OK
, "Got unexpected hr %#lx.\n", hr
);
7555 if (memory_info
.Budget
)
7557 ret
= WaitForSingleObject(event
, 1000);
7558 ok(ret
== WAIT_OBJECT_0
, "Expected event fired.\n");
7561 IDXGIAdapter3_UnregisterVideoMemoryBudgetChangeNotification(adapter3
, cookie
);
7562 IDXGIAdapter3_Release(adapter3
);
7566 IDXGIAdapter_Release(adapter
);
7567 refcount
= IDXGIDevice_Release(device
);
7568 ok(!refcount
, "Device has %lu references left.\n", refcount
);
7571 static void run_on_d3d10(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7573 IDXGIDevice
*device
;
7576 if (!(device
= create_device(0)))
7578 skip("Failed to create Direct3D 10 device.\n");
7582 test_func((IUnknown
*)device
, FALSE
);
7584 refcount
= IDXGIDevice_Release(device
);
7585 ok(!refcount
, "Device has %lu references left.\n", refcount
);
7588 static void run_on_d3d12(void (*test_func
)(IUnknown
*device
, BOOL is_d3d12
))
7590 ID3D12CommandQueue
*queue
;
7591 ID3D12Device
*device
;
7594 if (!(device
= create_d3d12_device()))
7596 skip("Failed to create Direct3D 12 device.\n");
7600 queue
= create_d3d12_direct_queue(device
);
7602 test_func((IUnknown
*)queue
, TRUE
);
7604 wait_queue_idle(device
, queue
);
7606 refcount
= ID3D12CommandQueue_Release(queue
);
7607 ok(!refcount
, "Command queue has %lu references left.\n", refcount
);
7608 refcount
= ID3D12Device_Release(device
);
7609 ok(!refcount
, "Device has %lu references left.\n", refcount
);
7614 HMODULE dxgi_module
, d3d11_module
, d3d12_module
, gdi32_module
;
7615 BOOL enable_debug_layer
= FALSE
;
7616 unsigned int argc
, i
;
7620 dxgi_module
= GetModuleHandleA("dxgi.dll");
7621 pCreateDXGIFactory1
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory1");
7622 pCreateDXGIFactory2
= (void *)GetProcAddress(dxgi_module
, "CreateDXGIFactory2");
7624 gdi32_module
= GetModuleHandleA("gdi32.dll");
7625 pD3DKMTCheckVidPnExclusiveOwnership
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCheckVidPnExclusiveOwnership");
7626 pD3DKMTCloseAdapter
= (void *)GetProcAddress(gdi32_module
, "D3DKMTCloseAdapter");
7627 pD3DKMTOpenAdapterFromGdiDisplayName
= (void *)GetProcAddress(gdi32_module
, "D3DKMTOpenAdapterFromGdiDisplayName");
7629 d3d11_module
= LoadLibraryA("d3d11.dll");
7630 pD3D11CreateDevice
= (void *)GetProcAddress(d3d11_module
, "D3D11CreateDevice");
7632 registry_mode
.dmSize
= sizeof(registry_mode
);
7633 ok(EnumDisplaySettingsW(NULL
, ENUM_REGISTRY_SETTINGS
, ®istry_mode
), "Failed to get display mode.\n");
7635 use_mt
= !getenv("WINETEST_NO_MT_D3D");
7636 /* Some host drivers (MacOS, Mesa radeonsi) never unmap memory even when
7637 * requested. When using the chunk allocator, running the tests with more
7638 * than one thread can exceed the 32-bit virtual address space. */
7639 if (sizeof(void *) == 4 && !strcmp(winetest_platform
, "wine"))
7642 argc
= winetest_get_mainargs(&argv
);
7643 for (i
= 2; i
< argc
; ++i
)
7645 if (!strcmp(argv
[i
], "--validate"))
7646 enable_debug_layer
= TRUE
;
7647 else if (!strcmp(argv
[i
], "--warp"))
7648 use_warp_adapter
= TRUE
;
7649 else if (!strcmp(argv
[i
], "--adapter") && i
+ 1 < argc
)
7650 use_adapter_idx
= atoi(argv
[++i
]);
7651 else if (!strcmp(argv
[i
], "--single"))
7655 queue_test(test_adapter_desc
);
7656 queue_test(test_adapter_luid
);
7657 queue_test(test_query_video_memory_info
);
7658 queue_test(test_check_interface_support
);
7659 queue_test(test_create_surface
);
7660 queue_test(test_parents
);
7661 queue_test(test_output
);
7662 queue_test(test_find_closest_matching_mode
);
7663 queue_test(test_resize_target_wndproc
);
7664 queue_test(test_create_factory
);
7665 queue_test(test_private_data
);
7666 queue_test(test_maximum_frame_latency
);
7667 queue_test(test_output_desc
);
7668 queue_test(test_object_wrapping
);
7669 queue_test(test_factory_check_feature_support
);
7670 queue_test(test_video_memory_budget_notification
);
7674 /* These tests use full-screen swapchains, so shouldn't run in parallel. */
7675 test_create_swapchain();
7676 test_inexact_modes();
7677 test_gamma_control();
7678 test_multi_adapter();
7679 test_swapchain_parameters();
7680 test_swapchain_window_messages();
7681 test_swapchain_window_styles();
7682 run_on_d3d10(test_set_fullscreen
);
7683 run_on_d3d10(test_resize_target
);
7684 run_on_d3d10(test_swapchain_resize
);
7685 run_on_d3d10(test_swapchain_present
);
7686 run_on_d3d10(test_swapchain_backbuffer_index
);
7687 run_on_d3d10(test_swapchain_formats
);
7688 run_on_d3d10(test_output_ownership
);
7689 run_on_d3d10(test_cursor_clipping
);
7690 run_on_d3d10(test_get_containing_output
);
7691 run_on_d3d10(test_window_association
);
7692 run_on_d3d10(test_default_fullscreen_target_output
);
7693 run_on_d3d10(test_mode_change
);
7694 run_on_d3d10(test_swapchain_present_count
);
7696 if (!(d3d12_module
= LoadLibraryA("d3d12.dll")))
7698 skip("Direct3D 12 is not available.\n");
7702 pD3D12CreateDevice
= (void *)GetProcAddress(d3d12_module
, "D3D12CreateDevice");
7703 pD3D12GetDebugInterface
= (void *)GetProcAddress(d3d12_module
, "D3D12GetDebugInterface");
7705 if (enable_debug_layer
&& SUCCEEDED(pD3D12GetDebugInterface(&IID_ID3D12Debug
, (void **)&debug
)))
7707 ID3D12Debug_EnableDebugLayer(debug
);
7708 ID3D12Debug_Release(debug
);
7711 run_on_d3d12(test_set_fullscreen
);
7712 run_on_d3d12(test_resize_target
);
7713 run_on_d3d12(test_swapchain_resize
);
7714 run_on_d3d12(test_swapchain_present
);
7715 run_on_d3d12(test_swapchain_backbuffer_index
);
7716 run_on_d3d12(test_swapchain_formats
);
7717 run_on_d3d12(test_output_ownership
);
7718 run_on_d3d12(test_cursor_clipping
);
7719 run_on_d3d12(test_frame_latency_event
);
7720 run_on_d3d12(test_colour_space_support
);
7721 run_on_d3d12(test_get_containing_output
);
7722 run_on_d3d12(test_window_association
);
7723 run_on_d3d12(test_default_fullscreen_target_output
);
7724 run_on_d3d12(test_mode_change
);
7725 run_on_d3d12(test_swapchain_present_count
);
7727 FreeLibrary(d3d12_module
);