d2d1: Properly aggregate render target implementations.
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> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9b11e371bb
commit
a7d8471638
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
return render_target->error.code;
|
||||
if (context->ops)
|
||||
{
|
||||
if (FAILED(hr = context->ops->device_context_present(context->outer_unknown)))
|
||||
context->error.code = hr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue