2 * Copyright 2014 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "d2d1_private.h"
23 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
25 static inline struct d2d_wic_render_target
*impl_from_IUnknown(IUnknown
*iface
)
27 return CONTAINING_RECORD(iface
, struct d2d_wic_render_target
, IUnknown_iface
);
30 static HRESULT
d2d_wic_render_target_present(IUnknown
*outer_unknown
)
32 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(outer_unknown
);
33 D3D10_MAPPED_TEXTURE2D mapped_texture
;
34 ID3D10Resource
*src_resource
;
35 IWICBitmapLock
*bitmap_lock
;
36 UINT dst_size
, dst_pitch
;
43 if (FAILED(hr
= IDXGISurface_QueryInterface(render_target
->dxgi_surface
,
44 &IID_ID3D10Resource
, (void **)&src_resource
)))
46 ERR("Failed to get source resource interface, hr %#lx.\n", hr
);
50 ID3D10Texture2D_GetDevice(render_target
->readback_texture
, &device
);
51 ID3D10Device_CopyResource(device
, (ID3D10Resource
*)render_target
->readback_texture
, src_resource
);
52 ID3D10Device_Release(device
);
53 ID3D10Resource_Release(src_resource
);
57 dst_rect
.Width
= render_target
->width
;
58 dst_rect
.Height
= render_target
->height
;
59 if (FAILED(hr
= IWICBitmap_Lock(render_target
->bitmap
, &dst_rect
, WICBitmapLockWrite
, &bitmap_lock
)))
61 ERR("Failed to lock destination bitmap, hr %#lx.\n", hr
);
65 if (FAILED(hr
= IWICBitmapLock_GetDataPointer(bitmap_lock
, &dst_size
, &dst
)))
67 ERR("Failed to get data pointer, hr %#lx.\n", hr
);
68 IWICBitmapLock_Release(bitmap_lock
);
72 if (FAILED(hr
= IWICBitmapLock_GetStride(bitmap_lock
, &dst_pitch
)))
74 ERR("Failed to get stride, hr %#lx.\n", hr
);
75 IWICBitmapLock_Release(bitmap_lock
);
79 if (FAILED(hr
= ID3D10Texture2D_Map(render_target
->readback_texture
, 0, D3D10_MAP_READ
, 0, &mapped_texture
)))
81 ERR("Failed to map readback texture, hr %#lx.\n", hr
);
82 IWICBitmapLock_Release(bitmap_lock
);
86 src
= mapped_texture
.pData
;
88 for (i
= 0; i
< render_target
->height
; ++i
)
90 memcpy(dst
, src
, render_target
->bpp
* render_target
->width
);
91 src
+= mapped_texture
.RowPitch
;
95 ID3D10Texture2D_Unmap(render_target
->readback_texture
, 0);
96 IWICBitmapLock_Release(bitmap_lock
);
102 static HRESULT STDMETHODCALLTYPE
d2d_wic_render_target_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
104 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
106 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
108 return IUnknown_QueryInterface(render_target
->dxgi_inner
, iid
, out
);
111 static ULONG STDMETHODCALLTYPE
d2d_wic_render_target_AddRef(IUnknown
*iface
)
113 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
114 ULONG refcount
= InterlockedIncrement(&render_target
->refcount
);
116 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
121 static ULONG STDMETHODCALLTYPE
d2d_wic_render_target_Release(IUnknown
*iface
)
123 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
124 ULONG refcount
= InterlockedDecrement(&render_target
->refcount
);
126 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
130 IWICBitmap_Release(render_target
->bitmap
);
131 ID3D10Texture2D_Release(render_target
->readback_texture
);
132 IUnknown_Release(render_target
->dxgi_inner
);
133 IDXGISurface_Release(render_target
->dxgi_surface
);
134 heap_free(render_target
);
140 static const struct IUnknownVtbl d2d_wic_render_target_vtbl
=
142 d2d_wic_render_target_QueryInterface
,
143 d2d_wic_render_target_AddRef
,
144 d2d_wic_render_target_Release
,
147 static const struct d2d_device_context_ops d2d_wic_render_target_ops
=
149 d2d_wic_render_target_present
,
152 HRESULT
d2d_wic_render_target_init(struct d2d_wic_render_target
*render_target
, ID2D1Factory1
*factory
,
153 ID3D10Device1
*d3d_device
, IWICBitmap
*bitmap
, const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
155 D3D10_TEXTURE2D_DESC texture_desc
;
156 ID3D10Texture2D
*texture
;
157 IDXGIDevice
*dxgi_device
;
161 render_target
->IUnknown_iface
.lpVtbl
= &d2d_wic_render_target_vtbl
;
163 if (FAILED(hr
= IWICBitmap_GetSize(bitmap
, &render_target
->width
, &render_target
->height
)))
165 WARN("Failed to get bitmap dimensions, hr %#lx.\n", hr
);
169 texture_desc
.Width
= render_target
->width
;
170 texture_desc
.Height
= render_target
->height
;
171 texture_desc
.MipLevels
= 1;
172 texture_desc
.ArraySize
= 1;
174 texture_desc
.Format
= desc
->pixelFormat
.format
;
175 if (texture_desc
.Format
== DXGI_FORMAT_UNKNOWN
)
177 WICPixelFormatGUID bitmap_format
;
179 if (FAILED(hr
= IWICBitmap_GetPixelFormat(bitmap
, &bitmap_format
)))
181 WARN("Failed to get bitmap format, hr %#lx.\n", hr
);
185 if (IsEqualGUID(&bitmap_format
, &GUID_WICPixelFormat32bppPBGRA
)
186 || IsEqualGUID(&bitmap_format
, &GUID_WICPixelFormat32bppBGR
))
188 texture_desc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
192 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&bitmap_format
));
193 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
197 switch (texture_desc
.Format
)
199 case DXGI_FORMAT_B8G8R8A8_UNORM
:
200 render_target
->bpp
= 4;
204 FIXME("Unhandled format %#x.\n", texture_desc
.Format
);
205 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
208 texture_desc
.SampleDesc
.Count
= 1;
209 texture_desc
.SampleDesc
.Quality
= 0;
210 texture_desc
.Usage
= D3D10_USAGE_DEFAULT
;
211 texture_desc
.BindFlags
= D3D10_BIND_RENDER_TARGET
| D3D10_BIND_SHADER_RESOURCE
;
212 texture_desc
.CPUAccessFlags
= 0;
213 texture_desc
.MiscFlags
= desc
->usage
& D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE
?
214 D3D10_RESOURCE_MISC_GDI_COMPATIBLE
: 0;
216 if (FAILED(hr
= ID3D10Device1_CreateTexture2D(d3d_device
, &texture_desc
, NULL
, &texture
)))
218 WARN("Failed to create texture, hr %#lx.\n", hr
);
222 hr
= ID3D10Texture2D_QueryInterface(texture
, &IID_IDXGISurface
, (void **)&render_target
->dxgi_surface
);
223 ID3D10Texture2D_Release(texture
);
226 WARN("Failed to get DXGI surface interface, hr %#lx.\n", hr
);
230 texture_desc
.Usage
= D3D10_USAGE_STAGING
;
231 texture_desc
.BindFlags
= 0;
232 texture_desc
.CPUAccessFlags
= D3D10_CPU_ACCESS_READ
;
233 texture_desc
.MiscFlags
= 0;
235 if (FAILED(hr
= ID3D10Device1_CreateTexture2D(d3d_device
, &texture_desc
, NULL
, &render_target
->readback_texture
)))
237 WARN("Failed to create readback texture, hr %#lx.\n", hr
);
238 IDXGISurface_Release(render_target
->dxgi_surface
);
242 if (FAILED(hr
= ID3D10Device1_QueryInterface(d3d_device
, &IID_IDXGIDevice
, (void **)&dxgi_device
)))
244 WARN("Failed to get DXGI device, hr %#lx.\n", hr
);
245 IDXGISurface_Release(render_target
->dxgi_surface
);
249 hr
= ID2D1Factory1_CreateDevice(factory
, dxgi_device
, &device
);
250 IDXGIDevice_Release(dxgi_device
);
253 WARN("Failed to create D2D device, hr %#lx.\n", hr
);
254 IDXGISurface_Release(render_target
->dxgi_surface
);
258 hr
= d2d_d3d_create_render_target(device
, render_target
->dxgi_surface
, &render_target
->IUnknown_iface
,
259 &d2d_wic_render_target_ops
, desc
, (void **)&render_target
->dxgi_inner
);
260 ID2D1Device_Release(device
);
263 WARN("Failed to create DXGI surface render target, hr %#lx.\n", hr
);
264 ID3D10Texture2D_Release(render_target
->readback_texture
);
265 IDXGISurface_Release(render_target
->dxgi_surface
);
269 if (FAILED(hr
= IUnknown_QueryInterface(render_target
->dxgi_inner
,
270 &IID_ID2D1RenderTarget
, (void **)&render_target
->dxgi_target
)))
272 WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#lx.\n", hr
);
273 IUnknown_Release(render_target
->dxgi_inner
);
274 ID3D10Texture2D_Release(render_target
->readback_texture
);
275 IDXGISurface_Release(render_target
->dxgi_surface
);
279 render_target
->bitmap
= bitmap
;
280 IWICBitmap_AddRef(bitmap
);