Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: call back on EndDraw/Flush.
dlls/d2d1/bitmap_render_target.c | 7 +++++- dlls/d2d1/d2d1_private.h | 13 +++++++++-- dlls/d2d1/dc_render_target.c | 34 ++++++++++++++-------------- dlls/d2d1/device.c | 38 ++++++++++++++++++++++---------- dlls/d2d1/hwnd_render_target.c | 21 ++++++++++-------- dlls/d2d1/wic_render_target.c | 37 ++++++++++++++++--------------- 6 files changed, 91 insertions(+), 59 deletions(-)
diff --git a/dlls/d2d1/bitmap_render_target.c b/dlls/d2d1/bitmap_render_target.c index c106e211d6..5ae155d430 100644 --- a/dlls/d2d1/bitmap_render_target.c +++ b/dlls/d2d1/bitmap_render_target.c @@ -733,6 +733,7 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta D2D1_COMPATIBLE_RENDER_TARGET_OPTIONS options) { D2D1_RENDER_TARGET_PROPERTIES dxgi_rt_desc; + struct outer_target_desc outer_desc; D2D1_BITMAP_PROPERTIES bitmap_desc; D3D10_TEXTURE2D_DESC texture_desc; IDXGISurface *dxgi_surface; @@ -810,8 +811,12 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta return hr; }
+ outer_desc.outer_unknown = (IUnknown *)&render_target->ID2D1BitmapRenderTarget_iface; + outer_desc.data = NULL; + outer_desc.present = NULL; + if (FAILED(hr = d2d_d3d_create_render_target(parent_target->factory, dxgi_surface, - (IUnknown *)&render_target->ID2D1BitmapRenderTarget_iface, &dxgi_rt_desc, &render_target->dxgi_target))) + &outer_desc, &dxgi_rt_desc, &render_target->dxgi_target))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); IDXGISurface_Release(dxgi_surface); diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index e00b942797..49d1475ed4 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -117,6 +117,15 @@ struct d2d_ps_cb struct d2d_brush_cb opacity_brush; };
+typedef HRESULT (*outer_target_present_func)(const void *data); + +struct outer_target_desc +{ + IUnknown *outer_unknown; + const void *data; + outer_target_present_func present; +}; + struct d2d_device_context { ID2D1DeviceContext ID2D1DeviceContext_iface; @@ -124,7 +133,7 @@ struct d2d_device_context IDWriteTextRenderer IDWriteTextRenderer_iface; LONG refcount;
- IUnknown *outer_unknown; + struct outer_target_desc outer_target;
ID2D1Factory *factory; ID3D10Device *device; @@ -148,7 +157,7 @@ struct d2d_device_context struct d2d_clip_stack clip_stack; };
-HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown, +HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, const struct outer_target_desc *outer, const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target) DECLSPEC_HIDDEN; HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *render_target, IDXGISurface1 *surface) DECLSPEC_HIDDEN;
diff --git a/dlls/d2d1/dc_render_target.c b/dlls/d2d1/dc_render_target.c index d5e4f47e6d..f5276bfbb4 100644 --- a/dlls/d2d1/dc_render_target.c +++ b/dlls/d2d1/dc_render_target.c @@ -24,17 +24,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void sync_bitmap(struct d2d_dc_render_target *render_target) +static HRESULT sync_bitmap(struct d2d_dc_render_target *render_target) { const RECT *dst_rect = &render_target->dst_rect; RECT empty_rect; HDC src_hdc; HRESULT hr;
+ if (!render_target->hdc) + return D2DERR_WRONG_STATE; + if (FAILED(hr = IDXGISurface1_GetDC(render_target->dxgi_surface, FALSE, &src_hdc))) { WARN("GetDC() failed, %#x.\n", hr); - return; + return S_OK; }
BitBlt(render_target->hdc, dst_rect->left, dst_rect->top, dst_rect->right - dst_rect->left, @@ -42,6 +45,8 @@ static void sync_bitmap(struct d2d_dc_render_target *render_target)
SetRectEmpty(&empty_rect); IDXGISurface1_ReleaseDC(render_target->dxgi_surface, &empty_rect); + + return S_OK; }
static inline struct d2d_dc_render_target *impl_from_ID2D1DCRenderTarget(ID2D1DCRenderTarget *iface) @@ -64,7 +69,8 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_QueryInterface(ID2D1DCRend *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) + else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget) + || IsEqualGUID(iid, &IID_ID2D1DeviceContext)) return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out);
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); @@ -524,14 +530,10 @@ static void STDMETHODCALLTYPE d2d_dc_render_target_PopLayer(ID2D1DCRenderTarget static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_Flush(ID2D1DCRenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2) { struct d2d_dc_render_target *render_target = impl_from_ID2D1DCRenderTarget(iface); - HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
- hr = ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); - sync_bitmap(render_target); - - return hr; + return ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); }
static void STDMETHODCALLTYPE d2d_dc_render_target_SaveDrawingState(ID2D1DCRenderTarget *iface, @@ -595,17 +597,10 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_EndDraw(ID2D1DCRenderTarge D2D1_TAG *tag1, D2D1_TAG *tag2) { struct d2d_dc_render_target *render_target = impl_from_ID2D1DCRenderTarget(iface); - HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
- if (!render_target->hdc) - return D2DERR_WRONG_STATE; - - hr = ID2D1RenderTarget_EndDraw(render_target->dxgi_target, tag1, tag2); - sync_bitmap(render_target); - - return hr; + return ID2D1RenderTarget_EndDraw(render_target->dxgi_target, tag1, tag2); }
static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_dc_render_target_GetPixelFormat(ID2D1DCRenderTarget *iface, @@ -816,6 +811,7 @@ static const struct ID2D1DCRenderTargetVtbl d2d_dc_render_target_vtbl = HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID2D1Factory *factory, ID3D10Device1 *device, const D2D1_RENDER_TARGET_PROPERTIES *desc) { + struct outer_target_desc outer_desc; D3D10_TEXTURE2D_DESC texture_desc; ID3D10Texture2D *texture; HRESULT hr; @@ -867,8 +863,12 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID return hr; }
+ outer_desc.outer_unknown = (IUnknown *)&render_target->ID2D1DCRenderTarget_iface; + outer_desc.data = render_target; + outer_desc.present = (outer_target_present_func)sync_bitmap; + if (FAILED(hr = d2d_d3d_create_render_target(factory, (IDXGISurface *)render_target->dxgi_surface, - (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, desc, &render_target->dxgi_target))) + &outer_desc, desc, &render_target->dxgi_target))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); IDXGISurface1_Release(render_target->dxgi_surface); diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index bba4870dd4..3980e35280 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -1448,8 +1448,13 @@ static void STDMETHODCALLTYPE d2d_device_context_PopLayer(ID2D1DeviceContext *if
static HRESULT STDMETHODCALLTYPE d2d_device_context_Flush(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2) { + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + FIXME("iface %p, tag1 %p, tag2 %p stub!\n", iface, tag1, tag2);
+ if (context->outer_target.present) + context->outer_target.present(context->outer_target.data); + return E_NOTIMPL; }
@@ -1615,16 +1620,23 @@ static void STDMETHODCALLTYPE d2d_device_context_BeginDraw(ID2D1DeviceContext *i static HRESULT STDMETHODCALLTYPE d2d_device_context_EndDraw(ID2D1DeviceContext *iface, D2D1_TAG *tag1, D2D1_TAG *tag2) { - struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
if (tag1) - *tag1 = render_target->error.tag1; + *tag1 = context->error.tag1; if (tag2) - *tag2 = render_target->error.tag2; + *tag2 = context->error.tag2;
- return render_target->error.code; + if (context->outer_target.present) + { + if (FAILED(hr = context->outer_target.present(context->outer_target.data))) + context->error.code = hr; + } + + return context->error.code; }
static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface, @@ -2381,7 +2393,7 @@ static HRESULT STDMETHODCALLTYPE d2d_gdi_interop_render_target_QueryInterface(ID
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
- return IUnknown_QueryInterface(render_target->outer_unknown, iid, out); + return IUnknown_QueryInterface(render_target->outer_target.outer_unknown, iid, out); }
static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInteropRenderTarget *iface) @@ -2390,7 +2402,7 @@ static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_AddRef(ID2D1GdiInte
TRACE("iface %p.\n", iface);
- return IUnknown_AddRef(render_target->outer_unknown); + return IUnknown_AddRef(render_target->outer_target.outer_unknown); }
static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInteropRenderTarget *iface) @@ -2399,7 +2411,7 @@ static ULONG STDMETHODCALLTYPE d2d_gdi_interop_render_target_Release(ID2D1GdiInt
TRACE("iface %p.\n", iface);
- return IUnknown_Release(render_target->outer_unknown); + return IUnknown_Release(render_target->outer_target.outer_unknown); }
static HRESULT d2d_device_context_get_surface(struct d2d_device_context *render_target, IDXGISurface1 **surface) @@ -2469,7 +2481,7 @@ static const struct ID2D1GdiInteropRenderTargetVtbl d2d_gdi_interop_render_targe };
static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, ID2D1Factory *factory, - IDXGISurface *surface, IUnknown *outer_unknown, const D2D1_RENDER_TARGET_PROPERTIES *desc) + IDXGISurface *surface, const struct outer_target_desc *outer, const D2D1_RENDER_TARGET_PROPERTIES *desc) { D3D10_SUBRESOURCE_DATA buffer_data; D3D10_STATE_BLOCK_MASK state_mask; @@ -3355,8 +3367,10 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, render_target->factory = factory; ID2D1Factory_AddRef(render_target->factory);
- render_target->outer_unknown = outer_unknown ? outer_unknown : - (IUnknown *)&render_target->ID2D1DeviceContext_iface; + if (outer) + render_target->outer_target = *outer; + else + render_target->outer_target.outer_unknown = (IUnknown *)&render_target->ID2D1DeviceContext_iface;
if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device))) { @@ -3554,7 +3568,7 @@ err: return hr; }
-HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown, +HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, const struct outer_target_desc *outer, const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target) { struct d2d_device_context *object; @@ -3563,7 +3577,7 @@ HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surfac if (!(object = heap_alloc_zero(sizeof(*object)))) return E_OUTOFMEMORY;
- if (FAILED(hr = d2d_device_context_init(object, factory, surface, outer_unknown, desc))) + if (FAILED(hr = d2d_device_context_init(object, factory, surface, outer, desc))) { WARN("Failed to initialize render target, hr %#x.\n", hr); heap_free(object); diff --git a/dlls/d2d1/hwnd_render_target.c b/dlls/d2d1/hwnd_render_target.c index 04d33536a6..112e6a98a2 100644 --- a/dlls/d2d1/hwnd_render_target.c +++ b/dlls/d2d1/hwnd_render_target.c @@ -24,12 +24,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void render_target_present(struct d2d_hwnd_render_target *render_target) +static HRESULT render_target_present(struct d2d_hwnd_render_target *render_target) { HRESULT hr;
if (FAILED(hr = IDXGISwapChain_Present(render_target->swapchain, render_target->sync_interval, 0))) WARN("Present failed, %#x.\n", hr); + + return S_OK; }
static inline struct d2d_hwnd_render_target *impl_from_ID2D1HwndRenderTarget(ID2D1HwndRenderTarget *iface) @@ -53,7 +55,8 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_QueryInterface(ID2D1Hwnd *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) + else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget) + || IsEqualGUID(iid, &IID_ID2D1DeviceContext)) return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out);
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); @@ -516,14 +519,10 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_Flush(ID2D1HwndRenderTar D2D1_TAG *tag2) { struct d2d_hwnd_render_target *render_target = impl_from_ID2D1HwndRenderTarget(iface); - HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
- hr = ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); - render_target_present(render_target); - - return hr; + return ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); }
static void STDMETHODCALLTYPE d2d_hwnd_render_target_SaveDrawingState(ID2D1HwndRenderTarget *iface, @@ -782,6 +781,7 @@ HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target { D2D1_RENDER_TARGET_PROPERTIES dxgi_rt_desc; DXGI_SWAP_CHAIN_DESC swapchain_desc; + struct outer_target_desc outer_desc; IDXGIAdapter *dxgi_adapter; IDXGIFactory *dxgi_factory; IDXGISurface *dxgi_surface; @@ -860,9 +860,12 @@ HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target return hr; }
+ outer_desc.outer_unknown = (IUnknown *)&render_target->ID2D1HwndRenderTarget_iface; + outer_desc.data = render_target; + outer_desc.present = (outer_target_present_func)render_target_present; + render_target->ID2D1HwndRenderTarget_iface.lpVtbl = &d2d_hwnd_render_target_vtbl; - hr = d2d_d3d_create_render_target(factory, dxgi_surface, (IUnknown *)&render_target->ID2D1HwndRenderTarget_iface, - &dxgi_rt_desc, &render_target->dxgi_target); + hr = d2d_d3d_create_render_target(factory, dxgi_surface, &outer_desc, &dxgi_rt_desc, &render_target->dxgi_target); IDXGISurface_Release(dxgi_surface); if (FAILED(hr)) { diff --git a/dlls/d2d1/wic_render_target.c b/dlls/d2d1/wic_render_target.c index 5642fd44ff..ede9d811d7 100644 --- a/dlls/d2d1/wic_render_target.c +++ b/dlls/d2d1/wic_render_target.c @@ -25,7 +25,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void sync_bitmap(struct d2d_wic_render_target *render_target) +static HRESULT sync_bitmap(struct d2d_wic_render_target *render_target) { D3D10_MAPPED_TEXTURE2D mapped_texture; ID3D10Resource *src_resource; @@ -41,7 +41,7 @@ static void sync_bitmap(struct d2d_wic_render_target *render_target) &IID_ID3D10Resource, (void **)&src_resource))) { ERR("Failed to get source resource interface, hr %#x.\n", hr); - return; + goto end; }
ID3D10Texture2D_GetDevice(render_target->readback_texture, &device); @@ -56,28 +56,28 @@ static void sync_bitmap(struct d2d_wic_render_target *render_target) if (FAILED(hr = IWICBitmap_Lock(render_target->bitmap, &dst_rect, WICBitmapLockWrite, &bitmap_lock))) { ERR("Failed to lock destination bitmap, hr %#x.\n", hr); - return; + goto end; }
if (FAILED(hr = IWICBitmapLock_GetDataPointer(bitmap_lock, &dst_size, &dst))) { ERR("Failed to get data pointer, hr %#x.\n", hr); IWICBitmapLock_Release(bitmap_lock); - return; + goto end; }
if (FAILED(hr = IWICBitmapLock_GetStride(bitmap_lock, &dst_pitch))) { ERR("Failed to get stride, hr %#x.\n", hr); IWICBitmapLock_Release(bitmap_lock); - return; + goto end; }
if (FAILED(hr = ID3D10Texture2D_Map(render_target->readback_texture, 0, D3D10_MAP_READ, 0, &mapped_texture))) { ERR("Failed to map readback texture, hr %#x.\n", hr); IWICBitmapLock_Release(bitmap_lock); - return; + goto end; }
src = mapped_texture.pData; @@ -91,6 +91,9 @@ static void sync_bitmap(struct d2d_wic_render_target *render_target)
ID3D10Texture2D_Unmap(render_target->readback_texture, 0); IWICBitmapLock_Release(bitmap_lock); + +end: + return S_OK; }
static inline struct d2d_wic_render_target *impl_from_ID2D1RenderTarget(ID2D1RenderTarget *iface) @@ -112,7 +115,8 @@ static HRESULT STDMETHODCALLTYPE d2d_wic_render_target_QueryInterface(ID2D1Rende *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) + else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget) + || IsEqualGUID(iid, &IID_ID2D1DeviceContext)) return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out);
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); @@ -574,14 +578,10 @@ static void STDMETHODCALLTYPE d2d_wic_render_target_PopLayer(ID2D1RenderTarget * static HRESULT STDMETHODCALLTYPE d2d_wic_render_target_Flush(ID2D1RenderTarget *iface, D2D1_TAG *tag1, D2D1_TAG *tag2) { struct d2d_wic_render_target *render_target = impl_from_ID2D1RenderTarget(iface); - HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
- hr = ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); - sync_bitmap(render_target); - - return hr; + return ID2D1RenderTarget_Flush(render_target->dxgi_target, tag1, tag2); }
static void STDMETHODCALLTYPE d2d_wic_render_target_SaveDrawingState(ID2D1RenderTarget *iface, @@ -645,14 +645,10 @@ static HRESULT STDMETHODCALLTYPE d2d_wic_render_target_EndDraw(ID2D1RenderTarget D2D1_TAG *tag1, D2D1_TAG *tag2) { struct d2d_wic_render_target *render_target = impl_from_ID2D1RenderTarget(iface); - HRESULT hr;
TRACE("iface %p, tag1 %p, tag2 %p.\n", iface, tag1, tag2);
- hr = ID2D1RenderTarget_EndDraw(render_target->dxgi_target, tag1, tag2); - sync_bitmap(render_target); - - return hr; + return ID2D1RenderTarget_EndDraw(render_target->dxgi_target, tag1, tag2); }
static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_wic_render_target_GetPixelFormat(ID2D1RenderTarget *iface, @@ -788,6 +784,7 @@ static const struct ID2D1RenderTargetVtbl d2d_wic_render_target_vtbl = HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, ID2D1Factory *factory, ID3D10Device1 *device, IWICBitmap *bitmap, const D2D1_RENDER_TARGET_PROPERTIES *desc) { + struct outer_target_desc outer_desc; D3D10_TEXTURE2D_DESC texture_desc; ID3D10Texture2D *texture; HRESULT hr; @@ -874,8 +871,12 @@ HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, return hr; }
+ outer_desc.outer_unknown = (IUnknown *)&render_target->ID2D1RenderTarget_iface; + outer_desc.data = render_target; + outer_desc.present = (outer_target_present_func)sync_bitmap; + if (FAILED(hr = d2d_d3d_create_render_target(factory, render_target->dxgi_surface, - (IUnknown *)&render_target->ID2D1RenderTarget_iface, desc, &render_target->dxgi_target))) + &outer_desc, desc, &render_target->dxgi_target))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); ID3D10Texture2D_Release(render_target->readback_texture);