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
20 #include "wine/port.h"
22 #include "d2d1_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
28 static inline struct d2d_wic_render_target
*impl_from_IUnknown(IUnknown
*iface
)
30 return CONTAINING_RECORD(iface
, struct d2d_wic_render_target
, IUnknown_iface
);
33 static HRESULT
d2d_wic_render_target_present(IUnknown
*outer_unknown
)
35 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(outer_unknown
);
36 D3D10_MAPPED_TEXTURE2D mapped_texture
;
37 ID3D10Resource
*src_resource
;
38 IWICBitmapLock
*bitmap_lock
;
39 UINT dst_size
, dst_pitch
;
46 if (FAILED(hr
= IDXGISurface_QueryInterface(render_target
->dxgi_surface
,
47 &IID_ID3D10Resource
, (void **)&src_resource
)))
49 ERR("Failed to get source resource interface, hr %#x.\n", hr
);
53 ID3D10Texture2D_GetDevice(render_target
->readback_texture
, &device
);
54 ID3D10Device_CopyResource(device
, (ID3D10Resource
*)render_target
->readback_texture
, src_resource
);
55 ID3D10Device_Release(device
);
56 ID3D10Resource_Release(src_resource
);
60 dst_rect
.Width
= render_target
->width
;
61 dst_rect
.Height
= render_target
->height
;
62 if (FAILED(hr
= IWICBitmap_Lock(render_target
->bitmap
, &dst_rect
, WICBitmapLockWrite
, &bitmap_lock
)))
64 ERR("Failed to lock destination bitmap, hr %#x.\n", hr
);
68 if (FAILED(hr
= IWICBitmapLock_GetDataPointer(bitmap_lock
, &dst_size
, &dst
)))
70 ERR("Failed to get data pointer, hr %#x.\n", hr
);
71 IWICBitmapLock_Release(bitmap_lock
);
75 if (FAILED(hr
= IWICBitmapLock_GetStride(bitmap_lock
, &dst_pitch
)))
77 ERR("Failed to get stride, hr %#x.\n", hr
);
78 IWICBitmapLock_Release(bitmap_lock
);
82 if (FAILED(hr
= ID3D10Texture2D_Map(render_target
->readback_texture
, 0, D3D10_MAP_READ
, 0, &mapped_texture
)))
84 ERR("Failed to map readback texture, hr %#x.\n", hr
);
85 IWICBitmapLock_Release(bitmap_lock
);
89 src
= mapped_texture
.pData
;
91 for (i
= 0; i
< render_target
->height
; ++i
)
93 memcpy(dst
, src
, render_target
->bpp
* render_target
->width
);
94 src
+= mapped_texture
.RowPitch
;
98 ID3D10Texture2D_Unmap(render_target
->readback_texture
, 0);
99 IWICBitmapLock_Release(bitmap_lock
);
105 static HRESULT STDMETHODCALLTYPE
d2d_wic_render_target_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
107 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
109 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
111 return IUnknown_QueryInterface(render_target
->dxgi_inner
, iid
, out
);
114 static ULONG STDMETHODCALLTYPE
d2d_wic_render_target_AddRef(IUnknown
*iface
)
116 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
117 ULONG refcount
= InterlockedIncrement(&render_target
->refcount
);
119 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
124 static ULONG STDMETHODCALLTYPE
d2d_wic_render_target_Release(IUnknown
*iface
)
126 struct d2d_wic_render_target
*render_target
= impl_from_IUnknown(iface
);
127 ULONG refcount
= InterlockedDecrement(&render_target
->refcount
);
129 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
133 IWICBitmap_Release(render_target
->bitmap
);
134 ID3D10Texture2D_Release(render_target
->readback_texture
);
135 IUnknown_Release(render_target
->dxgi_inner
);
136 IDXGISurface_Release(render_target
->dxgi_surface
);
137 heap_free(render_target
);
143 static const struct IUnknownVtbl d2d_wic_render_target_vtbl
=
145 d2d_wic_render_target_QueryInterface
,
146 d2d_wic_render_target_AddRef
,
147 d2d_wic_render_target_Release
,
150 static const struct d2d_device_context_ops d2d_wic_render_target_ops
=
152 d2d_wic_render_target_present
,
155 HRESULT
d2d_wic_render_target_init(struct d2d_wic_render_target
*render_target
, ID2D1Factory1
*factory
,
156 ID3D10Device1
*d3d_device
, IWICBitmap
*bitmap
, const D2D1_RENDER_TARGET_PROPERTIES
*desc
)
158 D3D10_TEXTURE2D_DESC texture_desc
;
159 ID3D10Texture2D
*texture
;
160 IDXGIDevice
*dxgi_device
;
164 render_target
->IUnknown_iface
.lpVtbl
= &d2d_wic_render_target_vtbl
;
166 if (FAILED(hr
= IWICBitmap_GetSize(bitmap
, &render_target
->width
, &render_target
->height
)))
168 WARN("Failed to get bitmap dimensions, hr %#x.\n", hr
);
172 texture_desc
.Width
= render_target
->width
;
173 texture_desc
.Height
= render_target
->height
;
174 texture_desc
.MipLevels
= 1;
175 texture_desc
.ArraySize
= 1;
177 texture_desc
.Format
= desc
->pixelFormat
.format
;
178 if (texture_desc
.Format
== DXGI_FORMAT_UNKNOWN
)
180 WICPixelFormatGUID bitmap_format
;
182 if (FAILED(hr
= IWICBitmap_GetPixelFormat(bitmap
, &bitmap_format
)))
184 WARN("Failed to get bitmap format, hr %#x.\n", hr
);
188 if (IsEqualGUID(&bitmap_format
, &GUID_WICPixelFormat32bppPBGRA
)
189 || IsEqualGUID(&bitmap_format
, &GUID_WICPixelFormat32bppBGR
))
191 texture_desc
.Format
= DXGI_FORMAT_B8G8R8A8_UNORM
;
195 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&bitmap_format
));
196 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
200 switch (texture_desc
.Format
)
202 case DXGI_FORMAT_B8G8R8A8_UNORM
:
203 render_target
->bpp
= 4;
207 FIXME("Unhandled format %#x.\n", texture_desc
.Format
);
208 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
211 texture_desc
.SampleDesc
.Count
= 1;
212 texture_desc
.SampleDesc
.Quality
= 0;
213 texture_desc
.Usage
= D3D10_USAGE_DEFAULT
;
214 texture_desc
.BindFlags
= D3D10_BIND_RENDER_TARGET
| D3D10_BIND_SHADER_RESOURCE
;
215 texture_desc
.CPUAccessFlags
= 0;
216 texture_desc
.MiscFlags
= desc
->usage
& D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE
?
217 D3D10_RESOURCE_MISC_GDI_COMPATIBLE
: 0;
219 if (FAILED(hr
= ID3D10Device1_CreateTexture2D(d3d_device
, &texture_desc
, NULL
, &texture
)))
221 WARN("Failed to create texture, hr %#x.\n", hr
);
225 hr
= ID3D10Texture2D_QueryInterface(texture
, &IID_IDXGISurface
, (void **)&render_target
->dxgi_surface
);
226 ID3D10Texture2D_Release(texture
);
229 WARN("Failed to get DXGI surface interface, hr %#x.\n", hr
);
233 texture_desc
.Usage
= D3D10_USAGE_STAGING
;
234 texture_desc
.BindFlags
= 0;
235 texture_desc
.CPUAccessFlags
= D3D10_CPU_ACCESS_READ
;
236 texture_desc
.MiscFlags
= 0;
238 if (FAILED(hr
= ID3D10Device1_CreateTexture2D(d3d_device
, &texture_desc
, NULL
, &render_target
->readback_texture
)))
240 WARN("Failed to create readback texture, hr %#x.\n", hr
);
241 IDXGISurface_Release(render_target
->dxgi_surface
);
245 if (FAILED(hr
= ID3D10Device1_QueryInterface(d3d_device
, &IID_IDXGIDevice
, (void **)&dxgi_device
)))
247 WARN("Failed to get DXGI device, hr %#x.\n", hr
);
248 IDXGISurface_Release(render_target
->dxgi_surface
);
252 hr
= ID2D1Factory1_CreateDevice(factory
, dxgi_device
, &device
);
253 IDXGIDevice_Release(dxgi_device
);
256 WARN("Failed to create D2D device, hr %#x.\n", hr
);
257 IDXGISurface_Release(render_target
->dxgi_surface
);
261 hr
= d2d_d3d_create_render_target(device
, render_target
->dxgi_surface
, &render_target
->IUnknown_iface
,
262 &d2d_wic_render_target_ops
, desc
, (void **)&render_target
->dxgi_inner
);
263 ID2D1Device_Release(device
);
266 WARN("Failed to create DXGI surface render target, hr %#x.\n", hr
);
267 ID3D10Texture2D_Release(render_target
->readback_texture
);
268 IDXGISurface_Release(render_target
->dxgi_surface
);
272 if (FAILED(hr
= IUnknown_QueryInterface(render_target
->dxgi_inner
,
273 &IID_ID2D1RenderTarget
, (void **)&render_target
->dxgi_target
)))
275 WARN("Failed to retrieve ID2D1RenderTarget interface, hr %#x.\n", hr
);
276 IUnknown_Release(render_target
->dxgi_inner
);
277 ID3D10Texture2D_Release(render_target
->readback_texture
);
278 IDXGISurface_Release(render_target
->dxgi_surface
);
282 render_target
->bitmap
= bitmap
;
283 IWICBitmap_AddRef(bitmap
);