[PATCH v3 4/6] dxgi: Implement d3d12_swapchain_GetFullscreenState() and d3d12_swapchain_SetFullscreenState().
Zhiyi Zhang
zzhang at codeweavers.com
Wed Jun 26 08:25:45 CDT 2019
On 2019/6/26 20:07, Conor McCarthy wrote:
> Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
> ---
> dlls/dxgi/swapchain.c | 144 ++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 140 insertions(+), 4 deletions(-)
>
> diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c
> index b7a3cc0..457d187 100644
> --- a/dlls/dxgi/swapchain.c
> +++ b/dlls/dxgi/swapchain.c
> @@ -1085,8 +1085,12 @@ struct d3d12_swapchain
> IWineDXGIFactory *factory;
>
> HWND window;
> + IDXGIOutput *target;
> DXGI_SWAP_CHAIN_DESC1 desc;
> DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc;
> + struct wined3d_window_state window_state;
> + DXGI_MODE_DESC original_mode;
> + RECT orig_window_rect;
> };
>
> static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format)
> @@ -2178,17 +2182,122 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetBuffer(IDXGISwapChain3 *ifac
> static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreenState(IDXGISwapChain3 *iface,
> BOOL fullscreen, IDXGIOutput *target)
> {
> - FIXME("iface %p, fullscreen %#x, target %p stub!\n", iface, fullscreen, target);
> + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
> + DXGI_SWAP_CHAIN_FULLSCREEN_DESC *fullscreen_desc = &swapchain->fullscreen_desc;
> + const DXGI_SWAP_CHAIN_DESC1 *swapchain_desc = &swapchain->desc;
> + HWND window = swapchain->window;
> + DXGI_MODE_DESC actual_mode;
> + HRESULT hr = S_OK;
>
> - return E_NOTIMPL;
> + TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target);
> +
> + if (!fullscreen && target)
> + {
> + WARN("Invalid call.\n");
> + return DXGI_ERROR_INVALID_CALL;
> + }
> +
> + if (target)
> + {
> + IDXGIOutput_AddRef(target);
> + }
> + else if (FAILED(hr = IDXGISwapChain3_GetContainingOutput(iface, &target)))
> + {
> + WARN("Failed to get default target output for swapchain, hr %#x.\n", hr);
> + return hr;
> + }
> +
> + wined3d_mutex_lock();
> +
> + if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH)
> + {
> + if (fullscreen)
> + {
> + actual_mode.Width = swapchain_desc->Width;
> + actual_mode.Height = swapchain_desc->Height;
> + actual_mode.RefreshRate = fullscreen_desc->RefreshRate;
> + actual_mode.Format = swapchain_desc->Format;
> + actual_mode.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
> + }
> + else
> + {
> + actual_mode = swapchain->original_mode;
> + }
> +
> + if (FAILED(hr = dxgi_output_set_display_mode(target, &actual_mode)))
> + goto release;
> + }
> + else
> + {
> + if (FAILED(hr = dxgi_output_get_display_mode(target, &actual_mode)))
> + {
> + ERR("Failed to get display mode, hr %#x.\n", hr);
> + hr = DXGI_ERROR_INVALID_CALL;
> + goto release;
> + }
> + }
> +
> + if (fullscreen)
> + {
> + if (fullscreen_desc->Windowed)
> + {
> + if (FAILED(hr = wined3d_window_setup_fullscreen(&swapchain->window_state,
> + window, actual_mode.Width, actual_mode.Height)))
> + goto release;
> + }
> + else
> + {
> + /* Fullscreen -> fullscreen mode change */
> + MoveWindow(window, 0, 0, actual_mode.Width, actual_mode.Height, TRUE);
> + ShowWindow(window, SW_SHOW);
> + }
> + }
> + else if (!fullscreen_desc->Windowed)
> + {
> + /* Fullscreen -> windowed switch */
> + wined3d_window_restore_from_fullscreen(&swapchain->window_state, window, &swapchain->orig_window_rect);
> + }
> +
> + wined3d_mutex_unlock();
> + fullscreen_desc->Windowed = !fullscreen;
> +
> + if (!fullscreen)
> + {
> + IDXGIOutput_Release(target);
> + target = NULL;
> + }
> +
> + if (swapchain->target)
> + IDXGIOutput_Release(swapchain->target);
> + swapchain->target = target;
> +
> + return S_OK;
> +
> +release:
> + wined3d_mutex_unlock();
> + IDXGIOutput_Release(target);
> +
> + return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
> }
>
> static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenState(IDXGISwapChain3 *iface,
> BOOL *fullscreen, IDXGIOutput **target)
> {
> - FIXME("iface %p, fullscreen %p, target %p stub!\n", iface, fullscreen, target);
> + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
>
> - return E_NOTIMPL;
> + TRACE("iface %p, fullscreen %p, target %p.\n", iface, fullscreen, target);
> +
> + if (fullscreen)
> + *fullscreen = !swapchain->fullscreen_desc.Windowed;
> +
> + if (target)
> + {
> + *target = swapchain->target;
> + if (*target)
> + IDXGIOutput_AddRef(*target);
> + }
> +
> + return S_OK;
> }
>
Hi Conor,
My dxgi patch yesterday have some todo_wines for d3d12 Set/GetFullscreenState.
Now they should start succeeding and you need to remove those todo_wines.
Thanks,
Zhiyi
> static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetDesc(IDXGISwapChain3 *iface, DXGI_SWAP_CHAIN_DESC *desc)
> @@ -2306,6 +2415,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapCh
>
> TRACE("iface %p, output %p.\n", iface, output);
>
> + if (swapchain->target)
> + {
> + IDXGIOutput_AddRef(*output = swapchain->target);
> + return S_OK;
> + }
> +
> device_parent = vkd3d_get_device_parent(swapchain->device);
>
> if (SUCCEEDED(hr = IUnknown_QueryInterface(device_parent, &IID_IDXGIAdapter, (void **)&adapter)))
> @@ -2752,6 +2867,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
> swapchain->refcount = 1;
>
> swapchain->window = window;
> + GetWindowRect(window, &swapchain->orig_window_rect);
> swapchain->desc = *swapchain_desc;
> swapchain->fullscreen_desc = *fullscreen_desc;
>
> @@ -2865,6 +2981,7 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu
> DXGI_SWAP_CHAIN_FULLSCREEN_DESC default_fullscreen_desc;
> struct d3d12_swapchain *object;
> ID3D12Device *device;
> + IDXGIOutput *output;
> HRESULT hr;
>
> if (swapchain_desc->Format == DXGI_FORMAT_UNKNOWN)
> @@ -2895,11 +3012,30 @@ HRESULT d3d12_swapchain_create(IWineDXGIFactory *factory, ID3D12CommandQueue *qu
> return hr;
> }
>
> + if (FAILED(hr = d3d12_swapchain_GetContainingOutput(&object->IDXGISwapChain3_iface, &output)))
> + {
> + ERR("Failed to get containing output, hr %#x.\n", hr);
> + goto cleanup;
> + }
> +
> + hr = dxgi_output_get_display_mode(output, &object->original_mode);
> + IDXGIOutput_Release(output);
> + if (FAILED(hr))
> + {
> + ERR("Failed to get current display mode, hr %#x.\n", hr);
> + goto cleanup;
> + }
> +
> TRACE("Created swapchain %p.\n", object);
>
> *swapchain = (IDXGISwapChain1 *)&object->IDXGISwapChain3_iface;
>
> return S_OK;
> +
> +cleanup:
> + d3d12_swapchain_destroy(object);
> + heap_free(object);
> + return hr;
> }
>
> #else
More information about the wine-devel
mailing list