[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