Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49395 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/d2d1/d2d1_private.h | 6 ++++- dlls/d2d1/device.c | 54 ++++++++++++++++++++++++++++++++++++++++ dlls/d2d1/tests/d2d1.c | 2 +- 3 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index cb3421478f0..e2794c8b1a2 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -27,7 +27,7 @@ #include <math.h> #define COBJMACROS #include "d2d1_2.h" -#include "d3d11.h" +#include "d3d11_1.h" #ifdef D2D1_INIT_GUID #include "initguid.h" #endif @@ -539,6 +539,10 @@ struct d2d_device ID2D1Factory1 *factory; IDXGIDevice *dxgi_device; ID3D10Device *d3d10_device; + ID3D11Device1 *d3d11_device; + ID3DDeviceContextState *d3d_dc_state; + ID3DDeviceContextState *prev_d3d_dc_state; + LONG d3d_dc_state_recursion; ID3D10Multithread *d3d10_mt; };
diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index cfa28e984f9..11722a19eed 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -2864,6 +2864,7 @@ static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_targe HRESULT d2d_device_get_d3d10_device(ID2D1Device *iface, ID3D10Device **d3d10_device) { struct d2d_device *device = unsafe_impl_from_ID2D1Device(iface); + ID3D11DeviceContext1 *d3d11_context;
if (!device->d3d10_device) { @@ -2873,6 +2874,16 @@ HRESULT d2d_device_get_d3d10_device(ID2D1Device *iface, ID3D10Device **d3d10_dev
if (device->d3d10_mt) ID3D10Multithread_Enter(device->d3d10_mt);
+ if (device->d3d11_device && !device->d3d_dc_state_recursion) + { + ID3D11Device1_GetImmediateContext1(device->d3d11_device, &d3d11_context); + ID3D11DeviceContext1_SwapDeviceContextState(d3d11_context, device->d3d_dc_state, &device->prev_d3d_dc_state); + ID3D11DeviceContext1_Release(d3d11_context); + device->d3d_dc_state_recursion = 1; + } + else if (device->d3d_dc_state_recursion) + device->d3d_dc_state_recursion++; + ID3D10Device_AddRef(*d3d10_device = device->d3d10_device); return S_OK; } @@ -2880,6 +2891,16 @@ HRESULT d2d_device_get_d3d10_device(ID2D1Device *iface, ID3D10Device **d3d10_dev void d2d_device_release_d3d10_device(ID2D1Device *iface, ID3D10Device *d3d10_device) { struct d2d_device *device = unsafe_impl_from_ID2D1Device(iface); + ID3D11DeviceContext1 *d3d11_context; + + if (device->d3d11_device && !--device->d3d_dc_state_recursion) + { + ID3D11Device1_GetImmediateContext1(device->d3d11_device, &d3d11_context); + ID3D11DeviceContext1_SwapDeviceContextState(d3d11_context, device->prev_d3d_dc_state, NULL); + ID3DDeviceContextState_Release(device->prev_d3d_dc_state); + ID3D11DeviceContext1_Release(d3d11_context); + device->prev_d3d_dc_state = NULL; + }
ID3D10Device_Release(d3d10_device);
@@ -4208,6 +4229,8 @@ static ULONG WINAPI d2d_device_Release(ID2D1Device *iface) if (!refcount) { if (device->d3d10_mt) ID3D10Multithread_Release(device->d3d10_mt); + if (device->d3d_dc_state) ID3DDeviceContextState_Release(device->d3d_dc_state); + if (device->d3d11_device) ID3D11Device1_Release(device->d3d11_device); if (device->d3d10_device) ID3D10Device_Release(device->d3d10_device); IDXGIDevice_Release(device->dxgi_device); ID2D1Factory1_Release(device->factory); @@ -4324,8 +4347,39 @@ void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevic
if (FAILED(hr = IDXGIDevice_QueryInterface(device->dxgi_device, &IID_ID3D10Device, (void **)&device->d3d10_device))) + { + ID3D11DeviceContext1 *d3d11_context; + DWORD levels = D3D_FEATURE_LEVEL_10_1; + + if (FAILED(hr = IDXGIDevice_QueryInterface(device->dxgi_device, + &IID_ID3D11Device1, (void **)&device->d3d11_device))) + goto done; + + if (FAILED(hr = ID3D11Device1_CreateDeviceContextState(device->d3d11_device, 0, + &levels, 1, D3D11_SDK_VERSION, &IID_ID3D10Device, NULL, &device->d3d_dc_state))) + goto done; + + ID3D11Device1_GetImmediateContext1(device->d3d11_device, &d3d11_context); + + if (device->d3d10_mt) ID3D10Multithread_Enter(device->d3d10_mt); + ID3D11DeviceContext1_SwapDeviceContextState(d3d11_context, device->d3d_dc_state, &device->prev_d3d_dc_state); + hr = ID3D11Device1_QueryInterface(device->d3d11_device, &IID_ID3D10Device, (void **)&device->d3d10_device); + ID3D11DeviceContext1_SwapDeviceContextState(d3d11_context, device->prev_d3d_dc_state, NULL); + if (device->d3d10_mt) ID3D10Multithread_Leave(device->d3d10_mt); + + ID3DDeviceContextState_Release(device->prev_d3d_dc_state); + ID3D11DeviceContext1_Release(d3d11_context); + device->prev_d3d_dc_state = NULL; + } + +done: + if (FAILED(hr)) { WARN("Failed to get device interface, hr %#x.\n", hr); device->d3d10_device = NULL; + if (device->d3d_dc_state) ID3DDeviceContextState_Release(device->d3d_dc_state); + device->d3d_dc_state = NULL; + if (device->d3d11_device) ID3D11Device1_Release(device->d3d11_device); + device->d3d11_device = NULL; } } diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 3e7df715dda..a1166b1ebb8 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -921,7 +921,7 @@ static ID2D1RenderTarget *create_render_target_desc(IDXGISurface *surface, hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, NULL, (void **)&factory); ok(SUCCEEDED(hr), "Failed to create factory, hr %#x.\n", hr); hr = ID2D1Factory_CreateDxgiSurfaceRenderTarget(factory, surface, desc, &render_target); - todo_wine_if(d3d11) ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); + ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr); ID2D1Factory_Release(factory);
if (FAILED(hr))