Module: wine Branch: master Commit: 282afc4450e71339ce366b55cdf454e05cc04a2b URL: http://source.winehq.org/git/wine.git/?a=commit;h=282afc4450e71339ce366b55cd...
Author: Józef Kucia jkucia@codeweavers.com Date: Tue Apr 12 12:29:38 2016 +0200
dxgi: Implement dxgi_swapchain_GetDevice().
Signed-off-by: Józef Kucia jkucia@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/d3d11/device.c | 2 +- dlls/dxgi/device.c | 12 +++++------- dlls/dxgi/dxgi_private.h | 3 ++- dlls/dxgi/factory.c | 2 +- dlls/dxgi/swapchain.c | 41 ++++++++++++++++++++++++++++++++++------- dlls/dxgi/tests/device.c | 2 +- include/wine/winedxgi.idl | 1 + 7 files changed, 45 insertions(+), 18 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 4f24c48..9144438 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -5064,7 +5064,7 @@ static HRESULT CDECL device_parent_create_swapchain(struct wined3d_device_parent return E_FAIL; }
- hr = IWineDXGIDevice_create_swapchain(wine_device, desc, swapchain); + hr = IWineDXGIDevice_create_swapchain(wine_device, desc, TRUE, swapchain); IWineDXGIDevice_Release(wine_device); if (FAILED(hr)) { diff --git a/dlls/dxgi/device.c b/dlls/dxgi/device.c index a10bb01..0c82383 100644 --- a/dlls/dxgi/device.c +++ b/dlls/dxgi/device.c @@ -310,31 +310,29 @@ static HRESULT STDMETHODCALLTYPE dxgi_device_create_surface(IWineDXGIDevice *ifa }
static HRESULT STDMETHODCALLTYPE dxgi_device_create_swapchain(IWineDXGIDevice *iface, - struct wined3d_swapchain_desc *desc, struct wined3d_swapchain **wined3d_swapchain) + struct wined3d_swapchain_desc *desc, BOOL implicit, struct wined3d_swapchain **wined3d_swapchain) { - struct dxgi_device *This = impl_from_IWineDXGIDevice(iface); + struct dxgi_device *device = impl_from_IWineDXGIDevice(iface); struct dxgi_swapchain *object; HRESULT hr;
TRACE("iface %p, desc %p, wined3d_swapchain %p.\n", iface, desc, wined3d_swapchain);
- object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); - if (!object) + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) { ERR("Failed to allocate DXGI swapchain object memory\n"); return E_OUTOFMEMORY; }
- hr = dxgi_swapchain_init(object, This, desc); - if (FAILED(hr)) + if (FAILED(hr = dxgi_swapchain_init(object, device, desc, implicit))) { WARN("Failed to initialize swapchain, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); return hr; }
- TRACE("Created IDXGISwapChain %p\n", object); + TRACE("Created IDXGISwapChain %p.\n", object); *wined3d_swapchain = object->wined3d_swapchain;
return S_OK; diff --git a/dlls/dxgi/dxgi_private.h b/dlls/dxgi/dxgi_private.h index 86d8608..fb49b21 100644 --- a/dlls/dxgi/dxgi_private.h +++ b/dlls/dxgi/dxgi_private.h @@ -157,10 +157,11 @@ struct dxgi_swapchain LONG refcount; struct wined3d_private_store private_store; struct wined3d_swapchain *wined3d_swapchain; + IWineDXGIDevice *device; };
HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device *device, - struct wined3d_swapchain_desc *desc) DECLSPEC_HIDDEN; + struct wined3d_swapchain_desc *desc, BOOL implicit) DECLSPEC_HIDDEN;
/* IDXGISurface */ struct dxgi_surface diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 5956e62..8e16311 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -246,7 +246,7 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_CreateSwapChain(IDXGIFactory1 *ifa wined3d_desc.swap_interval = WINED3DPRESENT_INTERVAL_DEFAULT; wined3d_desc.auto_restore_display_mode = TRUE;
- hr = IWineDXGIDevice_create_swapchain(dxgi_device, &wined3d_desc, &wined3d_swapchain); + hr = IWineDXGIDevice_create_swapchain(dxgi_device, &wined3d_desc, FALSE, &wined3d_swapchain); IWineDXGIDevice_Release(dxgi_device); if (FAILED(hr)) { diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 10a5786..b729970 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -70,16 +70,19 @@ static ULONG STDMETHODCALLTYPE dxgi_swapchain_AddRef(IDXGISwapChain *iface)
static ULONG STDMETHODCALLTYPE dxgi_swapchain_Release(IDXGISwapChain *iface) { - struct dxgi_swapchain *This = impl_from_IDXGISwapChain(iface); - ULONG refcount = InterlockedDecrement(&This->refcount); + struct dxgi_swapchain *swapchain = impl_from_IDXGISwapChain(iface); + ULONG refcount = InterlockedDecrement(&swapchain->refcount);
- TRACE("%p decreasing refcount to %u\n", This, refcount); + TRACE("%p decreasing refcount to %u.\n", swapchain, refcount);
if (!refcount) { + IWineDXGIDevice *device = swapchain->device; wined3d_mutex_lock(); - wined3d_swapchain_decref(This->wined3d_swapchain); + wined3d_swapchain_decref(swapchain->wined3d_swapchain); wined3d_mutex_unlock(); + if (device) + IWineDXGIDevice_Release(device); }
return refcount; @@ -128,9 +131,18 @@ static HRESULT STDMETHODCALLTYPE dxgi_swapchain_GetParent(IDXGISwapChain *iface,
static HRESULT STDMETHODCALLTYPE dxgi_swapchain_GetDevice(IDXGISwapChain *iface, REFIID riid, void **device) { - FIXME("iface %p, riid %s, device %p stub!\n", iface, debugstr_guid(riid), device); + struct dxgi_swapchain *swapchain = impl_from_IDXGISwapChain(iface);
- return E_NOTIMPL; + TRACE("iface %p, riid %s, device %p.\n", iface, debugstr_guid(riid), device); + + if (!swapchain->device) + { + ERR("Implicit swapchain does not store reference to device.\n"); + *device = NULL; + return E_NOINTERFACE; + } + + return IWineDXGIDevice_QueryInterface(swapchain->device, riid, device); }
/* IDXGISwapChain methods */ @@ -334,7 +346,7 @@ static const struct wined3d_parent_ops dxgi_swapchain_wined3d_parent_ops = };
HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device *device, - struct wined3d_swapchain_desc *desc) + struct wined3d_swapchain_desc *desc, BOOL implicit) { HRESULT hr;
@@ -353,5 +365,20 @@ HRESULT dxgi_swapchain_init(struct dxgi_swapchain *swapchain, struct dxgi_device } wined3d_mutex_unlock();
+ /** + * A reference to the implicit swapchain is held by the wined3d device. + * In order to avoid circular references we do not keep a reference + * to the device in the implicit swapchain. + */ + if (!implicit) + { + swapchain->device = &device->IWineDXGIDevice_iface; + IWineDXGIDevice_AddRef(swapchain->device); + } + else + { + swapchain->device = NULL; + } + return S_OK; } diff --git a/dlls/dxgi/tests/device.c b/dlls/dxgi/tests/device.c index 71385ab..837618a 100644 --- a/dlls/dxgi/tests/device.c +++ b/dlls/dxgi/tests/device.c @@ -479,7 +479,7 @@ static void test_create_swapchain(void) refcount = get_refcount((IUnknown *)factory); todo_wine ok(refcount == 4, "Got unexpected refcount %u.\n", refcount); refcount = get_refcount((IUnknown *)device); - todo_wine ok(refcount == 3, "Got unexpected refcount %u.\n", refcount); + ok(refcount == 3, "Got unexpected refcount %u.\n", refcount);
hr = IDXGISwapChain_GetDesc(swapchain, NULL); ok(hr == E_INVALIDARG, "GetDesc unexpectedly returned %#x.\n", hr); diff --git a/include/wine/winedxgi.idl b/include/wine/winedxgi.idl index d13a2f1..d9f6677 100644 --- a/include/wine/winedxgi.idl +++ b/include/wine/winedxgi.idl @@ -36,6 +36,7 @@ interface IWineDXGIDevice : IDXGIDevice1 ); HRESULT create_swapchain( [in] struct wined3d_swapchain_desc *desc, + [in] BOOL implicit, [out] struct wined3d_swapchain **wined3d_swapchain ); }