From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/dxgi/dxgi_private.h | 8 +++ dlls/dxgi/factory.c | 49 +++++++++++++++- dlls/dxgi/swapchain.c | 121 +++++++++++++++++++++++++++++++++++++++ dlls/dxgi/tests/dxgi.c | 15 ----- 4 files changed, 175 insertions(+), 18 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..b96539f12d9 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -387,6 +387,12 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d11_swapchain_SetFullscreen
TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!fullscreen && target) { WARN("Invalid call.\n"); @@ -520,6 +526,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_ResizeBuffers(IDXGISwapChain1 * TRACE("iface %p, buffer_count %u, width %u, height %u, format %s, flags %#x.\n", iface, buffer_count, width, height, debug_dxgi_format(format), flags);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION && (!width || !height)) + { + WARN("Invalid size for composition swapchains.\n"); + return E_INVALIDARG; + } + if (flags) FIXME("Ignoring flags %#x.\n", flags);
@@ -553,6 +565,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 +583,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); @@ -646,6 +670,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetFullscreenDesc(IDXGISwapChai
TRACE("iface %p, desc %p.\n", iface, desc);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!desc) { WARN("Invalid pointer.\n"); @@ -673,6 +703,12 @@ static HRESULT STDMETHODCALLTYPE d3d11_swapchain_GetHwnd(IDXGISwapChain1 *iface,
TRACE("iface %p, hwnd %p.\n", iface, hwnd);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!hwnd) { WARN("Invalid pointer.\n"); @@ -686,8 +722,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 +843,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 +912,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 +1069,7 @@ struct d3d12_swapchain ID3D12Device *device; IWineDXGIFactory *factory;
+ enum dxgi_swapchain_type type; HWND window; IDXGIOutput *target; DXGI_SWAP_CHAIN_DESC1 desc; @@ -1843,6 +1902,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"); @@ -2177,6 +2239,12 @@ static HRESULT STDMETHODCALLTYPE DECLSPEC_HOTPATCH d3d12_swapchain_SetFullscreen
TRACE("iface %p, fullscreen %#x, target %p.\n", iface, fullscreen, target);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!fullscreen && target) { WARN("Invalid call.\n"); @@ -2363,6 +2431,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers(IDXGISwapChain4 * TRACE("iface %p, buffer_count %u, width %u, height %u, format %s, flags %#x.\n", iface, buffer_count, width, height, debug_dxgi_format(format), flags);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION && (!width || !height)) + { + WARN("Invalid size for composition swapchains.\n"); + return E_INVALIDARG; + } + return d3d12_swapchain_resize_buffers(swapchain, buffer_count, width, height, format, flags); }
@@ -2373,6 +2447,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 +2467,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); @@ -2460,6 +2546,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetFullscreenDesc(IDXGISwapChai
TRACE("iface %p, desc %p.\n", iface, desc);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!desc) { WARN("Invalid pointer.\n"); @@ -2481,6 +2573,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetHwnd(IDXGISwapChain4 *iface,
TRACE("iface %p, hwnd %p.\n", iface, hwnd);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION) + { + WARN("Invalid swapchain type.\n"); + return DXGI_ERROR_INVALID_CALL; + } + if (!hwnd) { WARN("Invalid pointer.\n"); @@ -2494,8 +2592,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;
@@ -2700,6 +2806,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_ResizeBuffers1(IDXGISwapChain4 "node_mask %p, present_queue %p.\n", iface, buffer_count, width, height, debug_dxgi_format(format), flags, node_mask, present_queue);
+ if (swapchain->type == DXGI_SWAPCHAIN_TYPE_COMPOSITION && (!width || !height)) + { + WARN("Invalid size for composition swapchains.\n"); + return E_INVALIDARG; + } + if (!node_mask || !present_queue) return DXGI_ERROR_INVALID_CALL;
@@ -2902,6 +3014,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 cdb04ba2c0e..85f58055815 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -7629,58 +7629,43 @@ static void test_composition_swapchain(IUnknown *device, BOOL is_d3d12) ok(ref_count == !is_d3d12, "Factory has %lu references left.\n", ref_count); return; } - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "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, "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, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Width = 640;
/* Invalid height */ swapchain_desc.Height = 0; hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Height = 480;
/* 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, "Got unexpected hr %#lx.\n", hr); swapchain_desc.Scaling = DXGI_SCALING_STRETCH;
/* 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, "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, "Got unexpected hr %#lx.\n", hr);
/* Normal call*/ hr = IDXGIFactory2_CreateSwapChainForComposition(factory2, device, &swapchain_desc, NULL, &swapchain1); - todo_wine ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - if (FAILED(hr)) - { - skip("CreateSwapChainForComposition() is unsupported.\n"); - ref_count = IDXGIFactory2_Release(factory2); - ok(ref_count == !is_d3d12, "Factory has %lu references left.\n", ref_count); - return; - }
output = (void *)0xdeadbeef; hr = IDXGISwapChain1_GetFullscreenState(swapchain1, &ret, &output);