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"
25 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
27 static inline struct d2d_bitmap
*impl_from_ID2D1Bitmap(ID2D1Bitmap
*iface
)
29 return CONTAINING_RECORD(iface
, struct d2d_bitmap
, ID2D1Bitmap_iface
);
32 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_QueryInterface(ID2D1Bitmap
*iface
, REFIID iid
, void **out
)
34 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
36 if (IsEqualGUID(iid
, &IID_ID2D1Bitmap
)
37 || IsEqualGUID(iid
, &IID_ID2D1Image
)
38 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
39 || IsEqualGUID(iid
, &IID_IUnknown
))
41 ID2D1Bitmap_AddRef(iface
);
46 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
52 static ULONG STDMETHODCALLTYPE
d2d_bitmap_AddRef(ID2D1Bitmap
*iface
)
54 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
55 ULONG refcount
= InterlockedIncrement(&bitmap
->refcount
);
57 TRACE("%p increasing refcount to %u.\n", iface
, refcount
);
62 static ULONG STDMETHODCALLTYPE
d2d_bitmap_Release(ID2D1Bitmap
*iface
)
64 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
65 ULONG refcount
= InterlockedDecrement(&bitmap
->refcount
);
67 TRACE("%p decreasing refcount to %u.\n", iface
, refcount
);
71 ID3D10ShaderResourceView_Release(bitmap
->view
);
72 ID2D1Factory_Release(bitmap
->factory
);
73 HeapFree(GetProcessHeap(), 0, bitmap
);
79 static void STDMETHODCALLTYPE
d2d_bitmap_GetFactory(ID2D1Bitmap
*iface
, ID2D1Factory
**factory
)
81 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
83 TRACE("iface %p, factory %p.\n", iface
, factory
);
85 ID2D1Factory_AddRef(*factory
= bitmap
->factory
);
88 static D2D1_SIZE_F
* STDMETHODCALLTYPE
d2d_bitmap_GetSize(ID2D1Bitmap
*iface
, D2D1_SIZE_F
*size
)
90 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
92 TRACE("iface %p, size %p.\n", iface
, size
);
94 size
->width
= bitmap
->pixel_size
.width
/ (bitmap
->dpi_x
/ 96.0f
);
95 size
->height
= bitmap
->pixel_size
.height
/ (bitmap
->dpi_y
/ 96.0f
);
99 static D2D1_SIZE_U
* STDMETHODCALLTYPE
d2d_bitmap_GetPixelSize(ID2D1Bitmap
*iface
, D2D1_SIZE_U
*pixel_size
)
101 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
103 TRACE("iface %p, pixel_size %p.\n", iface
, pixel_size
);
105 *pixel_size
= bitmap
->pixel_size
;
109 static D2D1_PIXEL_FORMAT
* STDMETHODCALLTYPE
d2d_bitmap_GetPixelFormat(ID2D1Bitmap
*iface
, D2D1_PIXEL_FORMAT
*format
)
111 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
113 TRACE("iface %p, format %p.\n", iface
, format
);
115 *format
= bitmap
->format
;
119 static void STDMETHODCALLTYPE
d2d_bitmap_GetDpi(ID2D1Bitmap
*iface
, float *dpi_x
, float *dpi_y
)
121 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
123 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
125 *dpi_x
= bitmap
->dpi_x
;
126 *dpi_y
= bitmap
->dpi_y
;
129 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromBitmap(ID2D1Bitmap
*iface
,
130 const D2D1_POINT_2U
*dst_point
, ID2D1Bitmap
*bitmap
, const D2D1_RECT_U
*src_rect
)
132 FIXME("iface %p, dst_point %p, bitmap %p, src_rect %p stub!\n", iface
, dst_point
, bitmap
, src_rect
);
137 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromRenderTarget(ID2D1Bitmap
*iface
,
138 const D2D1_POINT_2U
*dst_point
, ID2D1RenderTarget
*render_target
, const D2D1_RECT_U
*src_rect
)
140 FIXME("iface %p, dst_point %p, render_target %p, src_rect %p stub!\n", iface
, dst_point
, render_target
, src_rect
);
145 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromMemory(ID2D1Bitmap
*iface
,
146 const D2D1_RECT_U
*dst_rect
, const void *src_data
, UINT32 pitch
)
148 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap(iface
);
149 ID3D10Device
*device
;
153 TRACE("iface %p, dst_rect %p, src_data %p, pitch %u.\n", iface
, dst_rect
, src_data
, pitch
);
157 box
.left
= dst_rect
->left
;
158 box
.top
= dst_rect
->top
;
160 box
.right
= dst_rect
->right
;
161 box
.bottom
= dst_rect
->bottom
;
165 ID3D10ShaderResourceView_GetResource(bitmap
->view
, &dst
);
166 ID3D10ShaderResourceView_GetDevice(bitmap
->view
, &device
);
167 ID3D10Device_UpdateSubresource(device
, dst
, 0, dst_rect
? &box
: NULL
, src_data
, pitch
, 0);
168 ID3D10Device_Release(device
);
169 ID3D10Resource_Release(dst
);
174 static const struct ID2D1BitmapVtbl d2d_bitmap_vtbl
=
176 d2d_bitmap_QueryInterface
,
179 d2d_bitmap_GetFactory
,
181 d2d_bitmap_GetPixelSize
,
182 d2d_bitmap_GetPixelFormat
,
184 d2d_bitmap_CopyFromBitmap
,
185 d2d_bitmap_CopyFromRenderTarget
,
186 d2d_bitmap_CopyFromMemory
,
189 static BOOL
format_supported(const D2D1_PIXEL_FORMAT
*format
)
193 static const D2D1_PIXEL_FORMAT supported_formats
[] =
195 {DXGI_FORMAT_R32G32B32A32_FLOAT
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
196 {DXGI_FORMAT_R32G32B32A32_FLOAT
, D2D1_ALPHA_MODE_IGNORE
},
197 {DXGI_FORMAT_R16G16B16A16_FLOAT
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
198 {DXGI_FORMAT_R16G16B16A16_FLOAT
, D2D1_ALPHA_MODE_IGNORE
},
199 {DXGI_FORMAT_R16G16B16A16_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
200 {DXGI_FORMAT_R16G16B16A16_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
201 {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
202 {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
203 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
204 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_IGNORE
},
205 {DXGI_FORMAT_A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
206 {DXGI_FORMAT_A8_UNORM
, D2D1_ALPHA_MODE_STRAIGHT
},
207 {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
208 {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
209 {DXGI_FORMAT_B8G8R8X8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
210 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
211 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_IGNORE
},
214 for (i
= 0; i
< ARRAY_SIZE(supported_formats
); ++i
)
216 if (supported_formats
[i
].format
== format
->format
217 && supported_formats
[i
].alphaMode
== format
->alphaMode
)
224 static void d2d_bitmap_init(struct d2d_bitmap
*bitmap
, ID2D1Factory
*factory
,
225 ID3D10ShaderResourceView
*view
, D2D1_SIZE_U size
, const D2D1_BITMAP_PROPERTIES
*desc
)
227 bitmap
->ID2D1Bitmap_iface
.lpVtbl
= &d2d_bitmap_vtbl
;
228 bitmap
->refcount
= 1;
229 ID2D1Factory_AddRef(bitmap
->factory
= factory
);
230 ID3D10ShaderResourceView_AddRef(bitmap
->view
= view
);
231 bitmap
->pixel_size
= size
;
232 bitmap
->format
= desc
->pixelFormat
;
233 bitmap
->dpi_x
= desc
->dpiX
;
234 bitmap
->dpi_y
= desc
->dpiY
;
236 if (bitmap
->dpi_x
== 0.0f
&& bitmap
->dpi_y
== 0.0f
)
238 bitmap
->dpi_x
= 96.0f
;
239 bitmap
->dpi_y
= 96.0f
;
243 HRESULT
d2d_bitmap_create(ID2D1Factory
*factory
, ID3D10Device
*device
, D2D1_SIZE_U size
, const void *src_data
,
244 UINT32 pitch
, const D2D1_BITMAP_PROPERTIES
*desc
, struct d2d_bitmap
**bitmap
)
246 D3D10_SUBRESOURCE_DATA resource_data
;
247 D3D10_TEXTURE2D_DESC texture_desc
;
248 ID3D10ShaderResourceView
*view
;
249 ID3D10Texture2D
*texture
;
252 if (!format_supported(&desc
->pixelFormat
))
254 WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
255 desc
->pixelFormat
.format
, desc
->pixelFormat
.alphaMode
);
256 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
259 texture_desc
.Width
= size
.width
;
260 texture_desc
.Height
= size
.height
;
261 texture_desc
.MipLevels
= 1;
262 texture_desc
.ArraySize
= 1;
263 texture_desc
.Format
= desc
->pixelFormat
.format
;
264 texture_desc
.SampleDesc
.Count
= 1;
265 texture_desc
.SampleDesc
.Quality
= 0;
266 texture_desc
.Usage
= D3D10_USAGE_DEFAULT
;
267 texture_desc
.BindFlags
= D3D10_BIND_SHADER_RESOURCE
;
268 texture_desc
.CPUAccessFlags
= 0;
269 texture_desc
.MiscFlags
= 0;
271 resource_data
.pSysMem
= src_data
;
272 resource_data
.SysMemPitch
= pitch
;
274 if (FAILED(hr
= ID3D10Device_CreateTexture2D(device
, &texture_desc
,
275 src_data
? &resource_data
: NULL
, &texture
)))
277 ERR("Failed to create texture, hr %#x.\n", hr
);
281 hr
= ID3D10Device_CreateShaderResourceView(device
, (ID3D10Resource
*)texture
, NULL
, &view
);
282 ID3D10Texture2D_Release(texture
);
285 ERR("Failed to create view, hr %#x.\n", hr
);
289 if ((*bitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**bitmap
))))
291 d2d_bitmap_init(*bitmap
, factory
, view
, size
, desc
);
292 TRACE("Created bitmap %p.\n", *bitmap
);
295 ID3D10ShaderResourceView_Release(view
);
297 return *bitmap
? S_OK
: E_OUTOFMEMORY
;
300 HRESULT
d2d_bitmap_create_shared(ID2D1RenderTarget
*render_target
, ID3D10Device
*target_device
,
301 REFIID iid
, void *data
, const D2D1_BITMAP_PROPERTIES
*desc
, struct d2d_bitmap
**bitmap
)
303 D2D1_BITMAP_PROPERTIES d
;
304 ID2D1Factory
*factory
;
306 if (IsEqualGUID(iid
, &IID_ID2D1Bitmap
))
308 struct d2d_bitmap
*src_impl
= unsafe_impl_from_ID2D1Bitmap(data
);
309 ID3D10Device
*device
;
312 ID2D1RenderTarget_GetFactory(render_target
, &factory
);
313 if (src_impl
->factory
!= factory
)
315 hr
= D2DERR_WRONG_FACTORY
;
319 ID3D10ShaderResourceView_GetDevice(src_impl
->view
, &device
);
320 ID3D10Device_Release(device
);
321 if (device
!= target_device
)
323 hr
= D2DERR_UNSUPPORTED_OPERATION
;
329 d
.pixelFormat
= src_impl
->format
;
330 d
.dpiX
= src_impl
->dpi_x
;
331 d
.dpiY
= src_impl
->dpi_y
;
335 if (!format_supported(&desc
->pixelFormat
))
337 WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
338 desc
->pixelFormat
.format
, desc
->pixelFormat
.alphaMode
);
339 hr
= D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
343 if (!(*bitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**bitmap
))))
349 d2d_bitmap_init(*bitmap
, factory
, src_impl
->view
, src_impl
->pixel_size
, desc
);
350 TRACE("Created bitmap %p.\n", *bitmap
);
353 ID2D1Factory_Release(factory
);
357 if (IsEqualGUID(iid
, &IID_IDXGISurface
) || IsEqualGUID(iid
, &IID_IDXGISurface1
))
359 ID3D10ShaderResourceView
*view
;
360 DXGI_SURFACE_DESC surface_desc
;
361 IDXGISurface
*surface
= data
;
362 ID3D10Resource
*resource
;
363 D2D1_SIZE_U pixel_size
;
364 ID3D10Device
*device
;
367 if (FAILED(IDXGISurface_QueryInterface(surface
, &IID_ID3D10Resource
, (void **)&resource
)))
369 WARN("Failed to get d3d resource from dxgi surface.\n");
373 ID3D10Resource_GetDevice(resource
, &device
);
374 ID3D10Device_Release(device
);
375 if (device
!= target_device
)
377 ID3D10Resource_Release(resource
);
378 return D2DERR_UNSUPPORTED_OPERATION
;
381 hr
= ID3D10Device_CreateShaderResourceView(target_device
, resource
, NULL
, &view
);
382 ID3D10Resource_Release(resource
);
385 WARN("Failed to create shader resource view, hr %#x.\n", hr
);
389 if (!(*bitmap
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(**bitmap
))))
391 ID3D10ShaderResourceView_Release(view
);
392 return E_OUTOFMEMORY
;
396 if (d
.dpiX
== 0.0f
|| d
.dpiY
== 0.0f
)
400 ID2D1RenderTarget_GetDpi(render_target
, &dpi_x
, &dpi_y
);
407 if (FAILED(hr
= IDXGISurface_GetDesc(surface
, &surface_desc
)))
409 WARN("Failed to get surface desc, hr %#x.\n", hr
);
410 ID3D10ShaderResourceView_Release(view
);
414 pixel_size
.width
= surface_desc
.Width
;
415 pixel_size
.height
= surface_desc
.Height
;
417 ID2D1RenderTarget_GetFactory(render_target
, &factory
);
418 d2d_bitmap_init(*bitmap
, factory
, view
, pixel_size
, &d
);
419 ID3D10ShaderResourceView_Release(view
);
420 ID2D1Factory_Release(factory
);
421 TRACE("Created bitmap %p.\n", *bitmap
);
426 WARN("Unhandled interface %s.\n", debugstr_guid(iid
));
431 HRESULT
d2d_bitmap_create_from_wic_bitmap(ID2D1Factory
*factory
, ID3D10Device
*device
, IWICBitmapSource
*bitmap_source
,
432 const D2D1_BITMAP_PROPERTIES
*desc
, struct d2d_bitmap
**bitmap
)
434 const D2D1_PIXEL_FORMAT
*d2d_format
;
435 D2D1_BITMAP_PROPERTIES bitmap_desc
;
436 WICPixelFormatGUID wic_format
;
437 unsigned int bpp
, data_size
;
447 const WICPixelFormatGUID
*wic
;
448 D2D1_PIXEL_FORMAT d2d
;
452 {&GUID_WICPixelFormat32bppPBGRA
, {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
}},
453 {&GUID_WICPixelFormat32bppBGR
, {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
}},
456 if (FAILED(hr
= IWICBitmapSource_GetSize(bitmap_source
, &size
.width
, &size
.height
)))
458 WARN("Failed to get bitmap size, hr %#x.\n", hr
);
464 bitmap_desc
.pixelFormat
.format
= DXGI_FORMAT_UNKNOWN
;
465 bitmap_desc
.pixelFormat
.alphaMode
= D2D1_ALPHA_MODE_UNKNOWN
;
466 bitmap_desc
.dpiX
= 0.0f
;
467 bitmap_desc
.dpiY
= 0.0f
;
474 if (FAILED(hr
= IWICBitmapSource_GetPixelFormat(bitmap_source
, &wic_format
)))
476 WARN("Failed to get bitmap format, hr %#x.\n", hr
);
480 for (i
= 0, d2d_format
= NULL
; i
< ARRAY_SIZE(format_lookup
); ++i
)
482 if (IsEqualGUID(&wic_format
, format_lookup
[i
].wic
))
484 d2d_format
= &format_lookup
[i
].d2d
;
491 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format
));
492 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
495 if (bitmap_desc
.pixelFormat
.format
== DXGI_FORMAT_UNKNOWN
)
496 bitmap_desc
.pixelFormat
.format
= d2d_format
->format
;
497 if (bitmap_desc
.pixelFormat
.alphaMode
== D2D1_ALPHA_MODE_UNKNOWN
)
498 bitmap_desc
.pixelFormat
.alphaMode
= d2d_format
->alphaMode
;
500 switch (bitmap_desc
.pixelFormat
.format
)
502 case DXGI_FORMAT_B8G8R8A8_UNORM
:
507 FIXME("Unhandled format %#x.\n", bitmap_desc
.pixelFormat
.format
);
508 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
511 pitch
= ((bpp
* size
.width
) + 15) & ~15;
512 data_size
= pitch
* size
.height
;
513 if (!(data
= HeapAlloc(GetProcessHeap(), 0, data_size
)))
514 return E_OUTOFMEMORY
;
518 rect
.Width
= size
.width
;
519 rect
.Height
= size
.height
;
520 if (FAILED(hr
= IWICBitmapSource_CopyPixels(bitmap_source
, &rect
, pitch
, data_size
, data
)))
522 WARN("Failed to copy bitmap pixels, hr %#x.\n", hr
);
523 HeapFree(GetProcessHeap(), 0, data
);
527 hr
= d2d_bitmap_create(factory
, device
, size
, data
, pitch
, &bitmap_desc
, bitmap
);
529 HeapFree(GetProcessHeap(), 0, data
);
534 struct d2d_bitmap
*unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap
*iface
)
538 assert(iface
->lpVtbl
== &d2d_bitmap_vtbl
);
539 return CONTAINING_RECORD(iface
, struct d2d_bitmap
, ID2D1Bitmap_iface
);