From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/dxgi_private.h | 8 ++++ dlls/dxgi/factory.c | 49 ++++++++++++++++++++-- dlls/dxgi/swapchain.c | 91 ++++++++++++++++++++++++++++++++++++++++ dlls/dxgi/tests/dxgi.c | 8 ---- 4 files changed, 145 insertions(+), 11 deletions(-)
diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index dd17e39eca6..e16a3211d2e 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -171,6 +171,12 @@ HRESULT dxgi_adapter_create(struct dxgi_factory *factory, UINT ordinal, struct dxgi_adapter *unsafe_impl_from_IDXGIAdapter(IDXGIAdapter *iface) DECLSPEC_HIDDEN;
/* IDXGISwapChain */ +enum dxgi_swapchain_type +{ + DXGI_SWAPCHAIN_TYPE_HWND, + DXGI_SWAPCHAIN_TYPE_COMPOSITION, +}; + struct d3d11_swapchain { IDXGISwapChain1 IDXGISwapChain1_iface; @@ -181,6 +187,8 @@ struct d3d11_swapchain IWineDXGIDevice *device; IWineDXGIFactory *factory;
+ enum dxgi_swapchain_type type; + HWND window; IDXGIOutput *target; LONG present_count; }; diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 8de882b388d..6e07530e7ef 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -381,10 +381,53 @@ static void STDMETHODCALLTYPE dxgi_factory_UnregisterOcclusionStatus(IWineDXGIFa static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChainForComposition(IWineDXGIFactory *iface, IUnknown *device, const DXGI_SWAP_CHAIN_DESC1 *desc, IDXGIOutput *output, IDXGISwapChain1 **swapchain) { - FIXME("iface %p, device %p, desc %p, output %p, swapchain %p stub!\n", - iface, device, desc, output, swapchain); + IWineDXGISwapChainFactory *swapchain_factory; + ID3D12CommandQueue *command_queue; + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, device %p, desc %p,, output %p, swapchain %p.\n", iface, device, desc, output, + swapchain); + + if (!device || !desc || !swapchain) + { + WARN("Invalid pointer.\n"); + return DXGI_ERROR_INVALID_CALL; + } + + if (desc->Stereo) + { + FIXME("Stereo swapchains are not supported.\n"); + return DXGI_ERROR_UNSUPPORTED; + } + + if (!desc->Width || !desc->Height + || desc->SwapEffect != DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL + || desc->Scaling != DXGI_SCALING_STRETCH) + return DXGI_ERROR_INVALID_CALL; + + if (!dxgi_validate_swapchain_desc(desc)) + return DXGI_ERROR_INVALID_CALL; + + if (output) + FIXME("Ignoring output %p.\n", output); + + if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_IWineDXGISwapChainFactory, (void **)&swapchain_factory))) + { + hr = IWineDXGISwapChainFactory_create_swapchain(swapchain_factory, (IDXGIFactory *)iface, + NULL, desc, NULL, output, swapchain); + IWineDXGISwapChainFactory_Release(swapchain_factory); + return hr; + } + + if (SUCCEEDED(IUnknown_QueryInterface(device, &IID_ID3D12CommandQueue, (void **)&command_queue))) + { + hr = d3d12_swapchain_create(iface, command_queue, NULL, desc, NULL, swapchain); + ID3D12CommandQueue_Release(command_queue); + return hr; + } + + ERR("This is not the device we're looking for.\n"); + return DXGI_ERROR_UNSUPPORTED; }
static UINT STDMETHODCALLTYPE dxgi_factory_GetCreationFlags(IWineDXGIFactory *iface) diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 9677142e0af..1d321a6bfc1 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -393,6 +393,12 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen return DXGI_ERROR_INVALID_CALL; }
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (target) { IDXGIOutput_AddRef(target); @@ -553,6 +559,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_ResizeTarget(IDXGISwapChain1 *i
TRACE("iface %p, target_mode_desc %p.\n", iface, target_mode_desc);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + state = wined3d_swapchain_get_state(swapchain->wined3d_swapchain);
return dxgi_swapchain_resize_target(state, target_mode_desc); @@ -565,6 +577,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetContainingOutput(IDXGISwapCh
TRACE("iface %p, output %p.\n", iface, output);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_UNSUPPORTED; + } + if (swapchain->target) { IDXGIOutput_AddRef(*output = swapchain->target); @@ -679,6 +697,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetHwnd(IDXGISwapChain1 *iface, return DXGI_ERROR_INVALID_CALL; }
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + *hwnd = d3d11_swapchain_get_hwnd(swapchain); return S_OK; } @@ -686,8 +710,16 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetHwnd(IDXGISwapChain1 *iface, static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetCoreWindow(IDXGISwapChain1 *iface, REFIID iid, void **core_window) { + struct d3d11_swapchain *swapchain = d3d11_swapchain_from_IDXGISwapChain1(iface); + FIXME("iface %p, iid %s, core_window %p stub!\n", iface, debugstr_guid(iid), core_window);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (core_window) *core_window = NULL;
@@ -799,6 +831,8 @@ static void STDMETHODCALLTYPE d3d11_swapchain_wined3d_object_released(void *pare { struct d3d11_swapchain *swapchain = parent;
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + DestroyWindow(swapchain->window); wined3d_private_store_cleanup(&swapchain->private_store); heap_free(parent); } @@ -866,6 +900,18 @@ HRESULT d3d11_swapchain_init(struct d3d11_swapchain *swapchain, struct dxgi_devi wined3d_mutex_lock(); wined3d_private_store_init(&swapchain->private_store);
+ if (!desc->device_window) + { + swapchain->type = DXGI_SWAPCHAIN_TYPE_COMPOSITION; + desc->device_window = CreateWindowW(L"static", L"dxgi_dummy_window", WS_POPUP, 0, 0, 1, 1, + 0, 0, 0, 0); + } + else + { + swapchain->type = DXGI_SWAPCHAIN_TYPE_HWND; + } + swapchain->window = desc->device_window; + if (!desc->windowed && (!desc->backbuffer_width || !desc->backbuffer_height)) FIXME("Fullscreen swapchain with back buffer width/height equal to 0 not supported properly.\n");
@@ -1011,6 +1057,7 @@ struct d3d12_swapchain ID3D12Device *device; IWineDXGIFactory *factory;
+ enum dxgi_swapchain_type type; HWND window; IDXGIOutput *target; DXGI_SWAP_CHAIN_DESC1 desc; @@ -1843,6 +1890,9 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain) if (swapchain->vk_instance) vk_funcs->p_vkDestroySurfaceKHR(swapchain->vk_instance, swapchain->vk_surface, NULL);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + DestroyWindow(swapchain->window); + if (swapchain->target) { WARN("Destroying fullscreen swapchain.\n"); @@ -2183,6 +2233,12 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreen return DXGI_ERROR_INVALID_CALL; }
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (target) { IDXGIOutput_AddRef(target); @@ -2373,6 +2429,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeTarget(IDXGISwapChain4 *i
TRACE("iface %p, target_mode_desc %p.\n", iface, target_mode_desc);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + return dxgi_swapchain_resize_target(swapchain->state, target_mode_desc); }
@@ -2387,6 +2449,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetContainingOutput(IDXGISwapCh
TRACE("iface %p, output %p.\n", iface, output);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_UNSUPPORTED; + } + if (swapchain->target) { IDXGIOutput_AddRef(*output = swapchain->target); @@ -2487,6 +2555,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetHwnd(IDXGISwapChain4 *iface, return DXGI_ERROR_INVALID_CALL; }
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + *hwnd = swapchain->window; return S_OK; } @@ -2494,8 +2568,16 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetHwnd(IDXGISwapChain4 *iface, static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetCoreWindow(IDXGISwapChain4 *iface, REFIID iid, void **core_window) { + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain4(iface); + FIXME("iface %p, iid %s, core_window %p stub!\n", iface, debugstr_guid(iid), core_window);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (core_window) *core_window = NULL;
@@ -2902,6 +2984,15 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI swapchain->state_parent.ops = &d3d12_swapchain_state_parent_ops; swapchain->refcount = 1;
+ if (!window) + { + swapchain->type = DXGI_SWAPCHAIN_TYPE_COMPOSITION; + window = CreateWindowW(L"static", L"dxgi_dummy_window", WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0); + } + else + { + swapchain->type = DXGI_SWAPCHAIN_TYPE_HWND; + } swapchain->window = window; swapchain->desc = *swapchain_desc; swapchain->fullscreen_desc = *fullscreen_desc; diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 5173a474195..c5dec94b459 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -7620,20 +7620,17 @@ static void test_composition_swapchain(IUnknown *device, BOOL is_d3d12) /* Parameter checks */ /* NULL device */ hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, NULL, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr);
/* NULL swapchain description */ hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, NULL, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr);
/* Invalid width */ swapchain_desc.Width = 0; hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Width = 640; @@ -7641,7 +7638,6 @@ static void test_composition_swapchain(IUnknown *device, BOOL is_d3d12) /* Invalid height */ swapchain_desc.Height = 0; hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Height = 480; @@ -7649,7 +7645,6 @@ static void test_composition_swapchain(IUnknown *device, BOOL is_d3d12) /* Invalid scaling */ swapchain_desc.Scaling = DXGI_SCALING_NONE; hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Scaling = DXGI_SCALING_STRETCH; @@ -7657,20 +7652,17 @@ static void test_composition_swapchain(IUnknown *device, BOOL is_d3d12) /* Invalid swap effect */ swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr); swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
/* NULL swapchain pointer */ hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, NULL); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr);
/* Normal call*/ hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == S_OK || broken(hr == DXGI_ERROR_UNSUPPORTED) /* Win7 */, "Got unexpected hr %#lx.\n", hr); if (FAILED(hr)) goto done;