[PATCH 3/6] dxgi: Handle creation and cleanup of D3D12 fullscreen swapchains.
Conor McCarthy
cmccarthy at codeweavers.com
Mon Oct 7 23:13:51 CDT 2019
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
dlls/dxgi/swapchain.c | 89 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 83 insertions(+), 6 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
index c76ad1d1..1787ced5 100644
--- a/dlls/dxgi/swapchain.c
+++ b/dlls/dxgi/swapchain.c
@@ -1877,6 +1877,10 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
{
const struct dxgi_vk_funcs *vk_funcs = &swapchain->vk_funcs;
void *vulkan_module = vk_funcs->vulkan_module;
+ struct dxgi_adapter *dxgi_adapter;
+ IUnknown *device_parent;
+ IDXGIAdapter *adapter;
+ HRESULT hr;
d3d12_swapchain_destroy_buffers(swapchain, TRUE);
@@ -1885,6 +1889,18 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
wined3d_private_store_cleanup(&swapchain->private_store);
+ device_parent = vkd3d_get_device_parent(swapchain->device);
+ if (SUCCEEDED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter)))
+ {
+ dxgi_adapter = unsafe_impl_from_IDXGIAdapter(adapter);
+ wined3d_swapchain_state_cleanup_fullscreen(swapchain->state, dxgi_adapter->factory->wined3d, dxgi_adapter->ordinal, NULL);
+ IDXGIAdapter_Release(adapter);
+ }
+ else
+ {
+ ERR("Failed to get adapter for fullscreen state cleanup, hr %#x.\n", hr);
+ }
+
if (swapchain->vk_device)
{
vk_funcs->p_vkDestroyFence(swapchain->vk_device, swapchain->vk_fence, NULL);
@@ -2807,6 +2823,36 @@ static BOOL init_vk_funcs(struct dxgi_vk_funcs *dxgi, VkInstance vk_instance, Vk
return TRUE;
}
+static HRESULT d3d12_swapchain_desc_adjust_display_mode(HWND window, struct wined3d_swapchain_desc *wined3d_desc,
+ const struct dxgi_adapter *dxgi_adapter)
+{
+ struct wined3d_display_mode wined3d_mode;
+ HRESULT hr;
+
+ wined3d_mode.width = wined3d_desc->backbuffer_width;
+ wined3d_mode.height = wined3d_desc->backbuffer_height;
+ wined3d_mode.refresh_rate = wined3d_desc->refresh_rate;
+ wined3d_mode.format_id = wined3d_desc->backbuffer_format;
+ wined3d_mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
+
+ wined3d_mutex_lock();
+ hr = wined3d_find_closest_matching_adapter_mode(dxgi_adapter->factory->wined3d, dxgi_adapter->ordinal, &wined3d_mode);
+ wined3d_mutex_unlock();
+
+ if (SUCCEEDED(hr))
+ {
+ if (wined3d_desc->backbuffer_width != wined3d_mode.width || wined3d_desc->backbuffer_height != wined3d_mode.height)
+ TRACE("Adjusting resolution from (%ux%u) to (%ux%u).\n", wined3d_desc->backbuffer_width,
+ wined3d_desc->backbuffer_height, wined3d_mode.width, wined3d_mode.height);
+ wined3d_desc->backbuffer_width = wined3d_mode.width;
+ wined3d_desc->backbuffer_height = wined3d_mode.height;
+ wined3d_desc->backbuffer_format = wined3d_mode.format_id;
+ wined3d_desc->refresh_rate = wined3d_mode.refresh_rate;
+ }
+
+ return hr;
+}
+
static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGIFactory *factory,
ID3D12Device *device, ID3D12CommandQueue *queue, HWND window,
const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc)
@@ -2867,10 +2913,21 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
IDXGIAdapter_Release(adapter);
if (FAILED(hr = wined3d_swapchain_desc_from_dxgi(&wined3d_desc, window, swapchain_desc, fullscreen_desc)))
return hr;
+
+ /* For fullscreen swapchains, D3D12 changes the swapchain size to match the mode resolution. */
+ if (!fullscreen_desc->Windowed && FAILED(hr = d3d12_swapchain_desc_adjust_display_mode(window,
+ &wined3d_desc, dxgi_adapter)))
+ ERR("Failed to adjust resolution for fullscreen swapchain, hr %#x.\n", hr);
+
+ wined3d_desc.windowed = TRUE;
if (FAILED(hr = wined3d_swapchain_state_create(&wined3d_desc, window,
dxgi_adapter->factory->wined3d, dxgi_adapter->ordinal, &swapchain->state)))
return hr;
+ swapchain->desc.Width = wined3d_desc.backbuffer_width;
+ swapchain->desc.Height = wined3d_desc.backbuffer_height;
+ swapchain->desc.Format = dxgi_format_from_wined3dformat(wined3d_desc.backbuffer_format);
+
if (swapchain_desc->BufferUsage && swapchain_desc->BufferUsage != DXGI_USAGE_RENDER_TARGET_OUTPUT)
FIXME("Ignoring buffer usage %#x.\n", swapchain_desc->BufferUsage);
if (swapchain_desc->Scaling != DXGI_SCALING_STRETCH)
@@ -2885,8 +2942,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
FIXME("Unhandled scanline ordering %#x.\n", fullscreen_desc->ScanlineOrdering);
if (fullscreen_desc->Scaling)
FIXME("Unhandled mode scaling %#x.\n", fullscreen_desc->Scaling);
- if (!fullscreen_desc->Windowed)
- FIXME("Fullscreen not supported yet.\n");
vk_instance = vkd3d_instance_get_vk_instance(vkd3d_instance_from_device(device));
vk_physical_device = vkd3d_get_vk_physical_device(device);
@@ -2930,10 +2985,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
ID3D12Device_AddRef(swapchain->device = device);
if (FAILED(hr = d3d12_swapchain_create_vulkan_swapchain(swapchain)))
- {
- d3d12_swapchain_destroy(swapchain);
- return hr;
- }
+ goto cleanup;
fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_desc.pNext = NULL;
@@ -2955,7 +3007,32 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
IWineDXGIFactory_AddRef(swapchain->factory = factory);
+ if (!fullscreen_desc->Windowed)
+ {
+ if (FAILED(hr = IDXGISwapChain3_GetContainingOutput(&swapchain->IDXGISwapChain3_iface,
+ &swapchain->target)))
+ {
+ ERR("Failed to get target output for fullscreen swapchain, hr %#x.\n", hr);
+ goto cleanup;
+ }
+
+ wined3d_desc.windowed = FALSE;
+ wined3d_mutex_lock();
+ hr = dxgi_swapchain_set_fullscreen_state(swapchain->state, &wined3d_desc, swapchain->target);
+ wined3d_mutex_unlock();
+ if (FAILED(hr))
+ {
+ WARN("Failed to set fullscreen state, hr %#x.\n", hr);
+ IDXGIOutput_Release(swapchain->target);
+ goto cleanup;
+ }
+ }
+
return S_OK;
+
+cleanup:
+ d3d12_swapchain_destroy(swapchain);
+ return hr;
}
HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *queue, HWND window,
--
2.23.0
More information about the wine-devel
mailing list