From: Nikolay Sivov nsivov@codeweavers.com
In order to expose the ID2D1DeviceContext interface for them.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Henri Verbeet hverbeet@codeweavers.com --- dlls/d2d1/bitmap_render_target.c | 23 ++++--- dlls/d2d1/d2d1_private.h | 14 ++++- dlls/d2d1/dc_render_target.c | 57 +++++++++-------- dlls/d2d1/device.c | 129 +++++++++++++++++++++++++++------------ dlls/d2d1/factory.c | 2 +- dlls/d2d1/hwnd_render_target.c | 51 +++++++++------- dlls/d2d1/wic_render_target.c | 61 ++++++++++-------- 7 files changed, 218 insertions(+), 119 deletions(-)
diff --git a/dlls/d2d1/bitmap_render_target.c b/dlls/d2d1/bitmap_render_target.c index c106e211d61..57f5b23b511 100644 --- a/dlls/d2d1/bitmap_render_target.c +++ b/dlls/d2d1/bitmap_render_target.c @@ -45,13 +45,8 @@ static HRESULT STDMETHODCALLTYPE d2d_bitmap_render_target_QueryInterface(ID2D1Bi *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) - return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out);
- WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - - *out = NULL; - return E_NOINTERFACE; + return IUnknown_QueryInterface(render_target->dxgi_inner, iid, out); }
static ULONG STDMETHODCALLTYPE d2d_bitmap_render_target_AddRef(ID2D1BitmapRenderTarget *iface) @@ -73,7 +68,7 @@ static ULONG STDMETHODCALLTYPE d2d_bitmap_render_target_Release(ID2D1BitmapRende
if (!refcount) { - ID2D1RenderTarget_Release(render_target->dxgi_target); + IUnknown_Release(render_target->dxgi_inner); ID2D1Bitmap_Release(render_target->bitmap); heap_free(render_target); } @@ -743,7 +738,6 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta FIXME("Compatible target options are ignored, %#x.\n", options);
render_target->ID2D1BitmapRenderTarget_iface.lpVtbl = &d2d_bitmap_render_target_vtbl; - render_target->refcount = 1;
dxgi_rt_desc.type = parent_target->desc.type; dxgi_rt_desc.usage = parent_target->desc.usage; @@ -811,13 +805,23 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta }
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))) + (IUnknown *)&render_target->ID2D1BitmapRenderTarget_iface, NULL, + &dxgi_rt_desc, (void **)&render_target->dxgi_inner))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); IDXGISurface_Release(dxgi_surface); return hr; }
+ if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, + &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) + { + WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); + IUnknown_Release(render_target->dxgi_inner); + IDXGISurface_Release(dxgi_surface); + return hr; + } + bitmap_desc.pixelFormat = dxgi_rt_desc.pixelFormat; bitmap_desc.dpiX = dxgi_rt_desc.dpiX; bitmap_desc.dpiY = dxgi_rt_desc.dpiY; @@ -829,6 +833,7 @@ HRESULT d2d_bitmap_render_target_init(struct d2d_bitmap_render_target *render_ta { WARN("Failed to create shared bitmap, hr %#x.\n", hr); ID2D1RenderTarget_Release(render_target->dxgi_target); + IUnknown_Release(render_target->dxgi_inner); return hr; }
diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index e00b9427977..f9fd8c72cd6 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -117,14 +117,21 @@ struct d2d_ps_cb struct d2d_brush_cb opacity_brush; };
+struct d2d_device_context_ops +{ + HRESULT (*device_context_present)(IUnknown *outer_unknown); +}; + struct d2d_device_context { ID2D1DeviceContext ID2D1DeviceContext_iface; ID2D1GdiInteropRenderTarget ID2D1GdiInteropRenderTarget_iface; IDWriteTextRenderer IDWriteTextRenderer_iface; + IUnknown IUnknown_iface; LONG refcount;
IUnknown *outer_unknown; + const struct d2d_device_context_ops *ops;
ID2D1Factory *factory; ID3D10Device *device; @@ -149,7 +156,8 @@ struct d2d_device_context };
HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown, - const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target) DECLSPEC_HIDDEN; + const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, + void **render_target) DECLSPEC_HIDDEN; HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *render_target, IDXGISurface1 *surface) DECLSPEC_HIDDEN;
struct d2d_wic_render_target @@ -159,6 +167,7 @@ struct d2d_wic_render_target
IDXGISurface *dxgi_surface; ID2D1RenderTarget *dxgi_target; + IUnknown *dxgi_inner; ID3D10Texture2D *readback_texture; IWICBitmap *bitmap;
@@ -177,6 +186,7 @@ struct d2d_dc_render_target
IDXGISurface1 *dxgi_surface; ID2D1RenderTarget *dxgi_target; + IUnknown *dxgi_inner;
RECT dst_rect; HDC hdc; @@ -191,6 +201,7 @@ struct d2d_hwnd_render_target LONG refcount;
ID2D1RenderTarget *dxgi_target; + IUnknown *dxgi_inner; IDXGISwapChain *swapchain; UINT sync_interval; HWND hwnd; @@ -206,6 +217,7 @@ struct d2d_bitmap_render_target LONG refcount;
ID2D1RenderTarget *dxgi_target; + IUnknown *dxgi_inner; ID2D1Bitmap *bitmap; };
diff --git a/dlls/d2d1/dc_render_target.c b/dlls/d2d1/dc_render_target.c index d5e4f47e6dd..8e43bcc3076 100644 --- a/dlls/d2d1/dc_render_target.c +++ b/dlls/d2d1/dc_render_target.c @@ -24,17 +24,26 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void sync_bitmap(struct d2d_dc_render_target *render_target) +static inline struct d2d_dc_render_target *impl_from_IUnknown(IUnknown *iface) { + return CONTAINING_RECORD(iface, struct d2d_dc_render_target, ID2D1DCRenderTarget_iface); +} + +static HRESULT d2d_dc_render_target_present(IUnknown *outer_unknown) +{ + struct d2d_dc_render_target *render_target = impl_from_IUnknown(outer_unknown); 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 +51,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,13 +75,8 @@ static HRESULT STDMETHODCALLTYPE d2d_dc_render_target_QueryInterface(ID2D1DCRend *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) - return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out); - - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
- *out = NULL; - return E_NOINTERFACE; + return IUnknown_QueryInterface(render_target->dxgi_inner, iid, out); }
static ULONG STDMETHODCALLTYPE d2d_dc_render_target_AddRef(ID2D1DCRenderTarget *iface) @@ -92,7 +98,7 @@ static ULONG STDMETHODCALLTYPE d2d_dc_render_target_Release(ID2D1DCRenderTarget
if (!refcount) { - ID2D1RenderTarget_Release(render_target->dxgi_target); + IUnknown_Release(render_target->dxgi_inner); IDXGISurface1_Release(render_target->dxgi_surface); heap_free(render_target); } @@ -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, @@ -813,6 +808,11 @@ static const struct ID2D1DCRenderTargetVtbl d2d_dc_render_target_vtbl = d2d_dc_render_target_BindDC, };
+static const struct d2d_device_context_ops d2d_dc_render_target_ops = +{ + d2d_dc_render_target_present, +}; + HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID2D1Factory *factory, ID3D10Device1 *device, const D2D1_RENDER_TARGET_PROPERTIES *desc) { @@ -821,7 +821,6 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID HRESULT hr;
render_target->ID2D1DCRenderTarget_iface.lpVtbl = &d2d_dc_render_target_vtbl; - render_target->refcount = 1;
/* Set with BindDC(). */ SetRectEmpty(&render_target->dst_rect); @@ -868,12 +867,22 @@ HRESULT d2d_dc_render_target_init(struct d2d_dc_render_target *render_target, ID }
if (FAILED(hr = d2d_d3d_create_render_target(factory, (IDXGISurface *)render_target->dxgi_surface, - (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, desc, &render_target->dxgi_target))) + (IUnknown *)&render_target->ID2D1DCRenderTarget_iface, &d2d_dc_render_target_ops, + desc, (void **)&render_target->dxgi_inner))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); IDXGISurface1_Release(render_target->dxgi_surface); return hr; }
+ if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, + &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) + { + WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); + IUnknown_Release(render_target->dxgi_inner); + IDXGISurface1_Release(render_target->dxgi_surface); + return hr; + } + return S_OK; } diff --git a/dlls/d2d1/device.c b/dlls/d2d1/device.c index bba4870dd4e..4478a19f9fd 100644 --- a/dlls/d2d1/device.c +++ b/dlls/d2d1/device.c @@ -193,6 +193,11 @@ static void d2d_device_context_draw(struct d2d_device_context *render_target, en WARN("Failed to apply stateblock, hr %#x.\n", hr); }
+static inline struct d2d_device_context *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_device_context, IUnknown_iface); +} + static inline struct d2d_device_context *impl_from_ID2D1DeviceContext(ID2D1DeviceContext *iface) { return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface); @@ -203,9 +208,9 @@ static inline struct d2d_device_context *impl_from_ID2D1RenderTarget(ID2D1Render return CONTAINING_RECORD(iface, struct d2d_device_context, ID2D1DeviceContext_iface); }
-static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out) +static HRESULT STDMETHODCALLTYPE d2d_device_context_inner_QueryInterface(IUnknown *iface, REFIID iid, void **out) { - struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); + struct d2d_device_context *context = impl_from_IUnknown(iface);
TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
@@ -214,14 +219,14 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceCo || IsEqualGUID(iid, &IID_ID2D1Resource) || IsEqualGUID(iid, &IID_IUnknown)) { - ID2D1DeviceContext_AddRef(iface); - *out = iface; + ID2D1DeviceContext_AddRef(&context->ID2D1DeviceContext_iface); + *out = &context->ID2D1DeviceContext_iface; return S_OK; } else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) { - ID2D1GdiInteropRenderTarget_AddRef(&render_target->ID2D1GdiInteropRenderTarget_iface); - *out = &render_target->ID2D1GdiInteropRenderTarget_iface; + ID2D1GdiInteropRenderTarget_AddRef(&context->ID2D1GdiInteropRenderTarget_iface); + *out = &context->ID2D1GdiInteropRenderTarget_iface; return S_OK; }
@@ -231,20 +236,20 @@ static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceCo return E_NOINTERFACE; }
-static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface) +static ULONG STDMETHODCALLTYPE d2d_device_context_inner_AddRef(IUnknown *iface) { - struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); - ULONG refcount = InterlockedIncrement(&render_target->refcount); + struct d2d_device_context *context = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&context->refcount);
TRACE("%p increasing refcount to %u.\n", iface, refcount);
return refcount; }
-static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface) +static ULONG STDMETHODCALLTYPE d2d_device_context_inner_Release(IUnknown *iface) { - struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); - ULONG refcount = InterlockedDecrement(&render_target->refcount); + struct d2d_device_context *context = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&context->refcount);
TRACE("%p decreasing refcount to %u.\n", iface, refcount);
@@ -252,30 +257,64 @@ static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *if { unsigned int i;
- d2d_clip_stack_cleanup(&render_target->clip_stack); - IDWriteRenderingParams_Release(render_target->default_text_rendering_params); - if (render_target->text_rendering_params) - IDWriteRenderingParams_Release(render_target->text_rendering_params); - ID3D10BlendState_Release(render_target->bs); - ID3D10RasterizerState_Release(render_target->rs); - ID3D10Buffer_Release(render_target->vb); - ID3D10Buffer_Release(render_target->ib); - ID3D10PixelShader_Release(render_target->ps); + d2d_clip_stack_cleanup(&context->clip_stack); + IDWriteRenderingParams_Release(context->default_text_rendering_params); + if (context->text_rendering_params) + IDWriteRenderingParams_Release(context->text_rendering_params); + ID3D10BlendState_Release(context->bs); + ID3D10RasterizerState_Release(context->rs); + ID3D10Buffer_Release(context->vb); + ID3D10Buffer_Release(context->ib); + ID3D10PixelShader_Release(context->ps); for (i = 0; i < D2D_SHAPE_TYPE_COUNT; ++i) { - ID3D10VertexShader_Release(render_target->shape_resources[i].vs); - ID3D10InputLayout_Release(render_target->shape_resources[i].il); + ID3D10VertexShader_Release(context->shape_resources[i].vs); + ID3D10InputLayout_Release(context->shape_resources[i].il); } - render_target->stateblock->lpVtbl->Release(render_target->stateblock); - ID3D10RenderTargetView_Release(render_target->view); - ID3D10Device_Release(render_target->device); - ID2D1Factory_Release(render_target->factory); - heap_free(render_target); + context->stateblock->lpVtbl->Release(context->stateblock); + ID3D10RenderTargetView_Release(context->view); + ID3D10Device_Release(context->device); + ID2D1Factory_Release(context->factory); + heap_free(context); }
return refcount; }
+static const struct IUnknownVtbl d2d_device_context_inner_unknown_vtbl = +{ + d2d_device_context_inner_QueryInterface, + d2d_device_context_inner_AddRef, + d2d_device_context_inner_Release, +}; + +static HRESULT STDMETHODCALLTYPE d2d_device_context_QueryInterface(ID2D1DeviceContext *iface, REFIID iid, void **out) +{ + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + return IUnknown_QueryInterface(context->outer_unknown, iid, out); +} + +static ULONG STDMETHODCALLTYPE d2d_device_context_AddRef(ID2D1DeviceContext *iface) +{ + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + + TRACE("iface %p.\n", iface); + + return IUnknown_AddRef(context->outer_unknown); +} + +static ULONG STDMETHODCALLTYPE d2d_device_context_Release(ID2D1DeviceContext *iface) +{ + struct d2d_device_context *context = impl_from_ID2D1DeviceContext(iface); + + TRACE("iface %p.\n", iface); + + return IUnknown_Release(context->outer_unknown); +} + static void STDMETHODCALLTYPE d2d_device_context_GetFactory(ID2D1DeviceContext *iface, ID2D1Factory **factory) { struct d2d_device_context *render_target = impl_from_ID2D1DeviceContext(iface); @@ -1448,8 +1487,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->ops) + context->ops->device_context_present(context->outer_unknown); + return E_NOTIMPL; }
@@ -1615,16 +1659,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; + + if (context->ops) + { + if (FAILED(hr = context->ops->device_context_present(context->outer_unknown))) + context->error.code = hr; + }
- return render_target->error.code; + return context->error.code; }
static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_device_context_GetPixelFormat(ID2D1DeviceContext *iface, @@ -2469,7 +2520,8 @@ 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, IUnknown *outer_unknown, const struct d2d_device_context_ops *ops, + const D2D1_RENDER_TARGET_PROPERTIES *desc) { D3D10_SUBRESOURCE_DATA buffer_data; D3D10_STATE_BLOCK_MASK state_mask; @@ -3351,12 +3403,13 @@ static HRESULT d2d_device_context_init(struct d2d_device_context *render_target, render_target->ID2D1DeviceContext_iface.lpVtbl = &d2d_device_context_vtbl; render_target->ID2D1GdiInteropRenderTarget_iface.lpVtbl = &d2d_gdi_interop_render_target_vtbl; render_target->IDWriteTextRenderer_iface.lpVtbl = &d2d_text_renderer_vtbl; + render_target->IUnknown_iface.lpVtbl = &d2d_device_context_inner_unknown_vtbl; render_target->refcount = 1; render_target->factory = factory; ID2D1Factory_AddRef(render_target->factory);
- render_target->outer_unknown = outer_unknown ? outer_unknown : - (IUnknown *)&render_target->ID2D1DeviceContext_iface; + render_target->outer_unknown = outer_unknown ? outer_unknown : &render_target->IUnknown_iface; + render_target->ops = ops;
if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_ID3D10Device, (void **)&render_target->device))) { @@ -3555,7 +3608,7 @@ err: }
HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surface, IUnknown *outer_unknown, - const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target) + const struct d2d_device_context_ops *ops, const D2D1_RENDER_TARGET_PROPERTIES *desc, void **render_target) { struct d2d_device_context *object; HRESULT hr; @@ -3563,7 +3616,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_unknown, ops, desc))) { WARN("Failed to initialize render target, hr %#x.\n", hr); heap_free(object); @@ -3571,7 +3624,7 @@ HRESULT d2d_d3d_create_render_target(ID2D1Factory *factory, IDXGISurface *surfac }
TRACE("Created render target %p.\n", object); - *render_target = (ID2D1RenderTarget *)&object->ID2D1DeviceContext_iface; + *render_target = outer_unknown ? &object->IUnknown_iface : (IUnknown *)&object->ID2D1DeviceContext_iface;
return S_OK; } diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c index d2e53879e69..b46d14c0d7e 100644 --- a/dlls/d2d1/factory.c +++ b/dlls/d2d1/factory.c @@ -340,7 +340,7 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDxgiSurfaceRenderTarget(ID2D1 { TRACE("iface %p, surface %p, desc %p, render_target %p.\n", iface, surface, desc, render_target);
- return d2d_d3d_create_render_target((ID2D1Factory *)iface, surface, NULL, desc, render_target); + return d2d_d3d_create_render_target((ID2D1Factory *)iface, surface, NULL, NULL, desc, (void **)render_target); }
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDCRenderTarget(ID2D1Factory1 *iface, diff --git a/dlls/d2d1/hwnd_render_target.c b/dlls/d2d1/hwnd_render_target.c index 04d33536a6e..1e763261197 100644 --- a/dlls/d2d1/hwnd_render_target.c +++ b/dlls/d2d1/hwnd_render_target.c @@ -24,12 +24,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void render_target_present(struct d2d_hwnd_render_target *render_target) +static inline struct d2d_hwnd_render_target *impl_from_IUnknown(IUnknown *iface) { + return CONTAINING_RECORD(iface, struct d2d_hwnd_render_target, ID2D1HwndRenderTarget_iface); +} + +static HRESULT d2d_hwnd_render_target_present(IUnknown *outer_unknown) +{ + struct d2d_hwnd_render_target *render_target = impl_from_IUnknown(outer_unknown); 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,13 +61,8 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_QueryInterface(ID2D1Hwnd *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) - return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out);
- WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - - *out = NULL; - return E_NOINTERFACE; + return IUnknown_QueryInterface(render_target->dxgi_inner, iid, out); }
static ULONG STDMETHODCALLTYPE d2d_hwnd_render_target_AddRef(ID2D1HwndRenderTarget *iface) @@ -81,7 +84,7 @@ static ULONG STDMETHODCALLTYPE d2d_hwnd_render_target_Release(ID2D1HwndRenderTar
if (!refcount) { - ID2D1RenderTarget_Release(render_target->dxgi_target); + IUnknown_Release(render_target->dxgi_inner); IDXGISwapChain_Release(render_target->swapchain); heap_free(render_target); } @@ -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, @@ -587,14 +586,10 @@ static HRESULT STDMETHODCALLTYPE d2d_hwnd_render_target_EndDraw(ID2D1HwndRenderT D2D1_TAG *tag1, 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_EndDraw(render_target->dxgi_target, tag1, tag2); - render_target_present(render_target); - - return hr; + return ID2D1RenderTarget_EndDraw(render_target->dxgi_target, tag1, tag2); }
static D2D1_PIXEL_FORMAT * STDMETHODCALLTYPE d2d_hwnd_render_target_GetPixelFormat(ID2D1HwndRenderTarget *iface, @@ -776,6 +771,11 @@ static const struct ID2D1HwndRenderTargetVtbl d2d_hwnd_render_target_vtbl = d2d_hwnd_render_target_GetHwnd };
+static const struct d2d_device_context_ops d2d_hwnd_render_target_ops = +{ + d2d_hwnd_render_target_present, +}; + HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target, ID2D1Factory *factory, ID3D10Device1 *device, const D2D1_RENDER_TARGET_PROPERTIES *desc, const D2D1_HWND_RENDER_TARGET_PROPERTIES *hwnd_rt_desc) @@ -792,7 +792,6 @@ HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target return HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE);
render_target->ID2D1HwndRenderTarget_iface.lpVtbl = &d2d_hwnd_render_target_vtbl; - render_target->refcount = 1; render_target->hwnd = hwnd_rt_desc->hwnd; render_target->sync_interval = hwnd_rt_desc->presentOptions & D2D1_PRESENT_OPTIONS_IMMEDIATELY ? 0 : 1;
@@ -861,8 +860,9 @@ HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target }
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, + (IUnknown *)&render_target->ID2D1HwndRenderTarget_iface, &d2d_hwnd_render_target_ops, + &dxgi_rt_desc, (void **)&render_target->dxgi_inner); IDXGISurface_Release(dxgi_surface); if (FAILED(hr)) { @@ -871,5 +871,14 @@ HRESULT d2d_hwnd_render_target_init(struct d2d_hwnd_render_target *render_target return hr; }
+ if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, + &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) + { + WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); + IUnknown_Release(render_target->dxgi_inner); + IDXGISwapChain_Release(render_target->swapchain); + return hr; + } + return S_OK; } diff --git a/dlls/d2d1/wic_render_target.c b/dlls/d2d1/wic_render_target.c index 5642fd44ff2..e342535838f 100644 --- a/dlls/d2d1/wic_render_target.c +++ b/dlls/d2d1/wic_render_target.c @@ -25,8 +25,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(d2d);
-static void sync_bitmap(struct d2d_wic_render_target *render_target) +static inline struct d2d_wic_render_target *impl_from_IUnknown(IUnknown *iface) { + return CONTAINING_RECORD(iface, struct d2d_wic_render_target, ID2D1RenderTarget_iface); +} + +static HRESULT d2d_wic_render_target_present(IUnknown *outer_unknown) +{ + struct d2d_wic_render_target *render_target = impl_from_IUnknown(outer_unknown); D3D10_MAPPED_TEXTURE2D mapped_texture; ID3D10Resource *src_resource; IWICBitmapLock *bitmap_lock; @@ -41,7 +47,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 +62,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 +97,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,13 +121,8 @@ static HRESULT STDMETHODCALLTYPE d2d_wic_render_target_QueryInterface(ID2D1Rende *out = iface; return S_OK; } - else if (IsEqualGUID(iid, &IID_ID2D1GdiInteropRenderTarget)) - return ID2D1RenderTarget_QueryInterface(render_target->dxgi_target, iid, out); - - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
- *out = NULL; - return E_NOINTERFACE; + return IUnknown_QueryInterface(render_target->dxgi_inner, iid, out); }
static ULONG STDMETHODCALLTYPE d2d_wic_render_target_AddRef(ID2D1RenderTarget *iface) @@ -142,7 +146,7 @@ static ULONG STDMETHODCALLTYPE d2d_wic_render_target_Release(ID2D1RenderTarget * { IWICBitmap_Release(render_target->bitmap); ID3D10Texture2D_Release(render_target->readback_texture); - ID2D1RenderTarget_Release(render_target->dxgi_target); + IUnknown_Release(render_target->dxgi_inner); IDXGISurface_Release(render_target->dxgi_surface); heap_free(render_target); } @@ -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, @@ -785,6 +781,11 @@ static const struct ID2D1RenderTargetVtbl d2d_wic_render_target_vtbl = d2d_wic_render_target_IsSupported, };
+static const struct d2d_device_context_ops d2d_wic_render_target_ops = +{ + d2d_wic_render_target_present, +}; + 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) { @@ -793,7 +794,6 @@ HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, HRESULT hr;
render_target->ID2D1RenderTarget_iface.lpVtbl = &d2d_wic_render_target_vtbl; - render_target->refcount = 1;
if (FAILED(hr = IWICBitmap_GetSize(bitmap, &render_target->width, &render_target->height))) { @@ -875,7 +875,8 @@ HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, }
if (FAILED(hr = d2d_d3d_create_render_target(factory, render_target->dxgi_surface, - (IUnknown *)&render_target->ID2D1RenderTarget_iface, desc, &render_target->dxgi_target))) + (IUnknown *)&render_target->ID2D1RenderTarget_iface, &d2d_wic_render_target_ops, + desc, (void **)&render_target->dxgi_inner))) { WARN("Failed to create DXGI surface render target, hr %#x.\n", hr); ID3D10Texture2D_Release(render_target->readback_texture); @@ -883,6 +884,16 @@ HRESULT d2d_wic_render_target_init(struct d2d_wic_render_target *render_target, return hr; }
+ if (FAILED(hr = IUnknown_QueryInterface(render_target->dxgi_inner, + &IID_ID2D1RenderTarget, (void **)&render_target->dxgi_target))) + { + WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr); + IUnknown_Release(render_target->dxgi_inner); + ID3D10Texture2D_Release(render_target->readback_texture); + IDXGISurface_Release(render_target->dxgi_surface); + return hr; + } + render_target->bitmap = bitmap; IWICBitmap_AddRef(bitmap);