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"
22 WINE_DEFAULT_DEBUG_CHANNEL(d2d
);
24 static inline struct d2d_bitmap
*impl_from_ID2D1Bitmap1(ID2D1Bitmap1
*iface
)
26 return CONTAINING_RECORD(iface
, struct d2d_bitmap
, ID2D1Bitmap1_iface
);
29 static HRESULT
d2d_bitmap_unmap(struct d2d_bitmap
*bitmap
)
31 ID3D11DeviceContext
*context
;
34 if (!bitmap
->mapped_resource
.pData
)
35 return D2DERR_WRONG_STATE
;
37 ID3D11Resource_GetDevice(bitmap
->resource
, &device
);
38 ID3D11Device_GetImmediateContext(device
, &context
);
39 ID3D11DeviceContext_Unmap(context
, bitmap
->resource
, 0);
40 ID3D11DeviceContext_Release(context
);
41 ID3D11Device_Release(device
);
43 memset(&bitmap
->mapped_resource
, 0, sizeof(bitmap
->mapped_resource
));
48 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_QueryInterface(ID2D1Bitmap1
*iface
, REFIID iid
, void **out
)
50 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
52 if (IsEqualGUID(iid
, &IID_ID2D1Bitmap1
)
53 || IsEqualGUID(iid
, &IID_ID2D1Bitmap
)
54 || IsEqualGUID(iid
, &IID_ID2D1Image
)
55 || IsEqualGUID(iid
, &IID_ID2D1Resource
)
56 || IsEqualGUID(iid
, &IID_IUnknown
))
58 ID2D1Bitmap1_AddRef(iface
);
63 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
69 static ULONG STDMETHODCALLTYPE
d2d_bitmap_AddRef(ID2D1Bitmap1
*iface
)
71 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
72 ULONG refcount
= InterlockedIncrement(&bitmap
->refcount
);
74 TRACE("%p increasing refcount to %lu.\n", iface
, refcount
);
79 static ULONG STDMETHODCALLTYPE
d2d_bitmap_Release(ID2D1Bitmap1
*iface
)
81 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
82 ULONG refcount
= InterlockedDecrement(&bitmap
->refcount
);
84 TRACE("%p decreasing refcount to %lu.\n", iface
, refcount
);
89 ID3D11ShaderResourceView_Release(bitmap
->srv
);
91 ID3D11RenderTargetView_Release(bitmap
->rtv
);
93 IDXGISurface_Release(bitmap
->surface
);
94 ID3D11Resource_Release(bitmap
->resource
);
95 ID2D1Factory_Release(bitmap
->factory
);
102 static void STDMETHODCALLTYPE
d2d_bitmap_GetFactory(ID2D1Bitmap1
*iface
, ID2D1Factory
**factory
)
104 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
106 TRACE("iface %p, factory %p.\n", iface
, factory
);
108 ID2D1Factory_AddRef(*factory
= bitmap
->factory
);
111 static D2D1_SIZE_F
* STDMETHODCALLTYPE
d2d_bitmap_GetSize(ID2D1Bitmap1
*iface
, D2D1_SIZE_F
*size
)
113 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
115 TRACE("iface %p, size %p.\n", iface
, size
);
117 size
->width
= bitmap
->pixel_size
.width
/ (bitmap
->dpi_x
/ 96.0f
);
118 size
->height
= bitmap
->pixel_size
.height
/ (bitmap
->dpi_y
/ 96.0f
);
122 static D2D1_SIZE_U
* STDMETHODCALLTYPE
d2d_bitmap_GetPixelSize(ID2D1Bitmap1
*iface
, D2D1_SIZE_U
*pixel_size
)
124 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
126 TRACE("iface %p, pixel_size %p.\n", iface
, pixel_size
);
128 *pixel_size
= bitmap
->pixel_size
;
132 static D2D1_PIXEL_FORMAT
* STDMETHODCALLTYPE
d2d_bitmap_GetPixelFormat(ID2D1Bitmap1
*iface
, D2D1_PIXEL_FORMAT
*format
)
134 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
136 TRACE("iface %p, format %p.\n", iface
, format
);
138 *format
= bitmap
->format
;
142 static void STDMETHODCALLTYPE
d2d_bitmap_GetDpi(ID2D1Bitmap1
*iface
, float *dpi_x
, float *dpi_y
)
144 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
146 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface
, dpi_x
, dpi_y
);
148 *dpi_x
= bitmap
->dpi_x
;
149 *dpi_y
= bitmap
->dpi_y
;
152 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromBitmap(ID2D1Bitmap1
*iface
,
153 const D2D1_POINT_2U
*dst_point
, ID2D1Bitmap
*bitmap
, const D2D1_RECT_U
*src_rect
)
155 struct d2d_bitmap
*src_bitmap
= unsafe_impl_from_ID2D1Bitmap(bitmap
);
156 struct d2d_bitmap
*dst_bitmap
= impl_from_ID2D1Bitmap1(iface
);
157 ID3D11DeviceContext
*context
;
158 ID3D11Device
*device
;
161 TRACE("iface %p, dst_point %p, bitmap %p, src_rect %p.\n", iface
, dst_point
, bitmap
, src_rect
);
165 box
.left
= src_rect
->left
;
166 box
.top
= src_rect
->top
;
168 box
.right
= src_rect
->right
;
169 box
.bottom
= src_rect
->bottom
;
173 ID3D11Resource_GetDevice(dst_bitmap
->resource
, &device
);
174 ID3D11Device_GetImmediateContext(device
, &context
);
175 ID3D11DeviceContext_CopySubresourceRegion(context
, dst_bitmap
->resource
, 0,
176 dst_point
? dst_point
->x
: 0, dst_point
? dst_point
->y
: 0, 0,
177 src_bitmap
->resource
, 0, src_rect
? &box
: NULL
);
178 ID3D11DeviceContext_Release(context
);
179 ID3D11Device_Release(device
);
184 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromRenderTarget(ID2D1Bitmap1
*iface
,
185 const D2D1_POINT_2U
*dst_point
, ID2D1RenderTarget
*render_target
, const D2D1_RECT_U
*src_rect
)
187 FIXME("iface %p, dst_point %p, render_target %p, src_rect %p stub!\n", iface
, dst_point
, render_target
, src_rect
);
192 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_CopyFromMemory(ID2D1Bitmap1
*iface
,
193 const D2D1_RECT_U
*dst_rect
, const void *src_data
, UINT32 pitch
)
195 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
196 ID3D11DeviceContext
*context
;
197 ID3D11Device
*device
;
200 TRACE("iface %p, dst_rect %p, src_data %p, pitch %u.\n", iface
, dst_rect
, src_data
, pitch
);
204 box
.left
= dst_rect
->left
;
205 box
.top
= dst_rect
->top
;
207 box
.right
= dst_rect
->right
;
208 box
.bottom
= dst_rect
->bottom
;
212 ID3D11Resource_GetDevice(bitmap
->resource
, &device
);
213 ID3D11Device_GetImmediateContext(device
, &context
);
214 ID3D11DeviceContext_UpdateSubresource(context
, bitmap
->resource
, 0, dst_rect
? &box
: NULL
, src_data
, pitch
, 0);
215 ID3D11DeviceContext_Release(context
);
216 ID3D11Device_Release(device
);
221 static void STDMETHODCALLTYPE
d2d_bitmap_GetColorContext(ID2D1Bitmap1
*iface
, ID2D1ColorContext
**context
)
223 FIXME("iface %p, context %p stub!\n", iface
, context
);
226 static D2D1_BITMAP_OPTIONS STDMETHODCALLTYPE
d2d_bitmap_GetOptions(ID2D1Bitmap1
*iface
)
228 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
230 TRACE("iface %p.\n", iface
);
232 return bitmap
->options
;
235 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_GetSurface(ID2D1Bitmap1
*iface
, IDXGISurface
**surface
)
237 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
239 TRACE("iface %p, surface %p.\n", iface
, surface
);
241 *surface
= bitmap
->surface
;
243 IDXGISurface_AddRef(*surface
);
245 return *surface
? S_OK
: D2DERR_INVALID_CALL
;
248 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_Map(ID2D1Bitmap1
*iface
, D2D1_MAP_OPTIONS options
,
249 D2D1_MAPPED_RECT
*mapped_rect
)
251 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
252 D3D11_MAPPED_SUBRESOURCE mapped_resource
;
253 ID3D11DeviceContext
*context
;
254 ID3D11Device
*device
;
258 TRACE("iface %p, options %#x, mapped_rect %p.\n", iface
, options
, mapped_rect
);
260 if (!(bitmap
->options
& D2D1_BITMAP_OPTIONS_CPU_READ
))
263 if (bitmap
->mapped_resource
.pData
)
264 return D2DERR_WRONG_STATE
;
266 if (options
== D2D1_MAP_OPTIONS_READ
)
267 map_type
= D3D11_MAP_READ
;
268 else if (options
== D2D1_MAP_OPTIONS_WRITE
)
269 map_type
= D3D11_MAP_WRITE
;
270 else if (options
== (D2D1_MAP_OPTIONS_READ
| D2D1_MAP_OPTIONS_WRITE
))
271 map_type
= D3D11_MAP_READ_WRITE
;
272 else if (options
== (D2D1_MAP_OPTIONS_WRITE
| D2D1_MAP_OPTIONS_DISCARD
))
273 map_type
= D3D11_MAP_WRITE_DISCARD
;
276 WARN("Invalid mapping options %#x.\n", options
);
280 ID3D11Resource_GetDevice(bitmap
->resource
, &device
);
281 ID3D11Device_GetImmediateContext(device
, &context
);
282 if (SUCCEEDED(hr
= ID3D11DeviceContext_Map(context
, bitmap
->resource
, 0, map_type
,
283 0, &mapped_resource
)))
285 bitmap
->mapped_resource
= mapped_resource
;
287 ID3D11DeviceContext_Release(context
);
288 ID3D11Device_Release(device
);
292 WARN("Failed to map resource, hr %#lx.\n", hr
);
296 mapped_rect
->pitch
= bitmap
->mapped_resource
.RowPitch
;
297 mapped_rect
->bits
= bitmap
->mapped_resource
.pData
;
302 static HRESULT STDMETHODCALLTYPE
d2d_bitmap_Unmap(ID2D1Bitmap1
*iface
)
304 struct d2d_bitmap
*bitmap
= impl_from_ID2D1Bitmap1(iface
);
306 TRACE("iface %p.\n", iface
);
308 return d2d_bitmap_unmap(bitmap
);
311 static const struct ID2D1Bitmap1Vtbl d2d_bitmap_vtbl
=
313 d2d_bitmap_QueryInterface
,
316 d2d_bitmap_GetFactory
,
318 d2d_bitmap_GetPixelSize
,
319 d2d_bitmap_GetPixelFormat
,
321 d2d_bitmap_CopyFromBitmap
,
322 d2d_bitmap_CopyFromRenderTarget
,
323 d2d_bitmap_CopyFromMemory
,
324 d2d_bitmap_GetColorContext
,
325 d2d_bitmap_GetOptions
,
326 d2d_bitmap_GetSurface
,
331 static BOOL
format_supported(const D2D1_PIXEL_FORMAT
*format
)
335 static const D2D1_PIXEL_FORMAT supported_formats
[] =
337 {DXGI_FORMAT_R32G32B32A32_FLOAT
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
338 {DXGI_FORMAT_R32G32B32A32_FLOAT
, D2D1_ALPHA_MODE_IGNORE
},
339 {DXGI_FORMAT_R16G16B16A16_FLOAT
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
340 {DXGI_FORMAT_R16G16B16A16_FLOAT
, D2D1_ALPHA_MODE_IGNORE
},
341 {DXGI_FORMAT_R16G16B16A16_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
342 {DXGI_FORMAT_R16G16B16A16_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
343 {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
344 {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
345 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
346 {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_IGNORE
},
347 {DXGI_FORMAT_A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
348 {DXGI_FORMAT_A8_UNORM
, D2D1_ALPHA_MODE_STRAIGHT
},
349 {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
350 {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
351 {DXGI_FORMAT_B8G8R8X8_UNORM
, D2D1_ALPHA_MODE_IGNORE
},
352 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_PREMULTIPLIED
},
353 {DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
, D2D1_ALPHA_MODE_IGNORE
},
356 for (i
= 0; i
< ARRAY_SIZE(supported_formats
); ++i
)
358 if (supported_formats
[i
].format
== format
->format
359 && supported_formats
[i
].alphaMode
== format
->alphaMode
)
366 static void d2d_bitmap_init(struct d2d_bitmap
*bitmap
, struct d2d_device_context
*context
,
367 ID3D11Resource
*resource
, D2D1_SIZE_U size
, const D2D1_BITMAP_PROPERTIES1
*desc
)
369 ID3D11Device
*d3d_device
;
372 bitmap
->ID2D1Bitmap1_iface
.lpVtbl
= &d2d_bitmap_vtbl
;
373 bitmap
->refcount
= 1;
374 ID2D1Factory_AddRef(bitmap
->factory
= context
->factory
);
375 ID3D11Resource_AddRef(bitmap
->resource
= resource
);
376 bitmap
->pixel_size
= size
;
377 bitmap
->format
= desc
->pixelFormat
;
378 bitmap
->dpi_x
= desc
->dpiX
;
379 bitmap
->dpi_y
= desc
->dpiY
;
380 bitmap
->options
= desc
->bitmapOptions
;
382 if (d2d_device_context_is_dxgi_target(context
))
383 ID3D11Resource_QueryInterface(resource
, &IID_IDXGISurface
, (void **)&bitmap
->surface
);
385 ID3D11Resource_GetDevice(resource
, &d3d_device
);
386 if (bitmap
->options
& D2D1_BITMAP_OPTIONS_TARGET
)
388 if (FAILED(hr
= ID3D11Device_CreateRenderTargetView(d3d_device
, resource
, NULL
, &bitmap
->rtv
)))
389 WARN("Failed to create RTV, hr %#lx.\n", hr
);
392 if (!(bitmap
->options
& D2D1_BITMAP_OPTIONS_CANNOT_DRAW
))
394 if (FAILED(hr
= ID3D11Device_CreateShaderResourceView(d3d_device
, resource
, NULL
, &bitmap
->srv
)))
395 WARN("Failed to create SRV, hr %#lx.\n", hr
);
397 ID3D11Device_Release(d3d_device
);
399 if (bitmap
->dpi_x
== 0.0f
&& bitmap
->dpi_y
== 0.0f
)
401 bitmap
->dpi_x
= 96.0f
;
402 bitmap
->dpi_y
= 96.0f
;
406 static BOOL
check_bitmap_options(unsigned int options
)
410 case D2D1_BITMAP_OPTIONS_NONE
:
411 case D2D1_BITMAP_OPTIONS_TARGET
:
412 case D2D1_BITMAP_OPTIONS_TARGET
| D2D1_BITMAP_OPTIONS_CANNOT_DRAW
:
413 case D2D1_BITMAP_OPTIONS_TARGET
| D2D1_BITMAP_OPTIONS_CANNOT_DRAW
| D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE
:
414 case D2D1_BITMAP_OPTIONS_TARGET
| D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE
:
415 case D2D1_BITMAP_OPTIONS_CANNOT_DRAW
| D2D1_BITMAP_OPTIONS_CPU_READ
:
418 WARN("Invalid bitmap options %#x.\n", options
);
423 HRESULT
d2d_bitmap_create(struct d2d_device_context
*context
, D2D1_SIZE_U size
, const void *src_data
,
424 UINT32 pitch
, const D2D1_BITMAP_PROPERTIES1
*desc
, struct d2d_bitmap
**bitmap
)
426 D3D11_SUBRESOURCE_DATA resource_data
;
427 D2D1_BITMAP_PROPERTIES1 bitmap_desc
;
428 D3D11_TEXTURE2D_DESC texture_desc
;
429 ID3D11Texture2D
*texture
;
432 if (!format_supported(&desc
->pixelFormat
))
434 WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
435 desc
->pixelFormat
.format
, desc
->pixelFormat
.alphaMode
);
436 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
439 if (desc
->dpiX
== 0.0f
&& desc
->dpiY
== 0.0f
)
442 bitmap_desc
.dpiX
= context
->desc
.dpiX
;
443 bitmap_desc
.dpiY
= context
->desc
.dpiY
;
446 else if (desc
->dpiX
<= 0.0f
|| desc
->dpiY
<= 0.0f
)
451 if (!check_bitmap_options(desc
->bitmapOptions
))
454 texture_desc
.Width
= size
.width
;
455 texture_desc
.Height
= size
.height
;
456 if (!texture_desc
.Width
|| !texture_desc
.Height
)
457 texture_desc
.Width
= texture_desc
.Height
= 1;
458 texture_desc
.MipLevels
= 1;
459 texture_desc
.ArraySize
= 1;
460 texture_desc
.Format
= desc
->pixelFormat
.format
;
461 texture_desc
.SampleDesc
.Count
= 1;
462 texture_desc
.SampleDesc
.Quality
= 0;
463 texture_desc
.Usage
= D3D11_USAGE_DEFAULT
;
464 if (desc
->bitmapOptions
& D2D1_BITMAP_OPTIONS_CPU_READ
)
465 texture_desc
.Usage
= D3D11_USAGE_STAGING
;
466 texture_desc
.BindFlags
= 0;
467 if (desc
->bitmapOptions
& D2D1_BITMAP_OPTIONS_TARGET
)
468 texture_desc
.BindFlags
|= D3D11_BIND_RENDER_TARGET
;
469 if (!(desc
->bitmapOptions
& D2D1_BITMAP_OPTIONS_CANNOT_DRAW
))
470 texture_desc
.BindFlags
|= D3D11_BIND_SHADER_RESOURCE
;
471 texture_desc
.CPUAccessFlags
= 0;
472 if (desc
->bitmapOptions
& D2D1_BITMAP_OPTIONS_CPU_READ
)
473 texture_desc
.CPUAccessFlags
|= D3D11_CPU_ACCESS_READ
;
474 texture_desc
.MiscFlags
= 0;
475 if (desc
->bitmapOptions
& D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE
)
476 texture_desc
.MiscFlags
|= D3D11_RESOURCE_MISC_GDI_COMPATIBLE
;
478 resource_data
.pSysMem
= src_data
;
479 resource_data
.SysMemPitch
= pitch
;
481 if (FAILED(hr
= ID3D11Device1_CreateTexture2D(context
->d3d_device
, &texture_desc
,
482 src_data
? &resource_data
: NULL
, &texture
)))
484 ERR("Failed to create texture, hr %#lx.\n", hr
);
488 if ((*bitmap
= calloc(1, sizeof(**bitmap
))))
490 d2d_bitmap_init(*bitmap
, context
, (ID3D11Resource
*)texture
, size
, desc
);
491 TRACE("Created bitmap %p.\n", *bitmap
);
493 ID3D11Texture2D_Release(texture
);
495 return *bitmap
? S_OK
: E_OUTOFMEMORY
;
498 unsigned int d2d_get_bitmap_options_for_surface(IDXGISurface
*surface
)
500 D3D11_TEXTURE2D_DESC desc
;
501 unsigned int options
= 0;
502 ID3D11Texture2D
*texture
;
504 if (FAILED(IDXGISurface_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture
)))
507 ID3D11Texture2D_GetDesc(texture
, &desc
);
508 ID3D11Texture2D_Release(texture
);
510 if (desc
.BindFlags
& D3D11_BIND_RENDER_TARGET
)
511 options
|= D2D1_BITMAP_OPTIONS_TARGET
;
512 if (!(desc
.BindFlags
& D3D11_BIND_SHADER_RESOURCE
))
513 options
|= D2D1_BITMAP_OPTIONS_CANNOT_DRAW
;
514 if (desc
.MiscFlags
& D3D11_RESOURCE_MISC_GDI_COMPATIBLE
)
515 options
|= D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE
;
516 if (desc
.Usage
== D3D11_USAGE_STAGING
&& desc
.CPUAccessFlags
& D3D11_CPU_ACCESS_READ
)
517 options
|= D2D1_BITMAP_OPTIONS_CPU_READ
;
522 HRESULT
d2d_bitmap_create_shared(struct d2d_device_context
*context
, REFIID iid
, void *data
,
523 const D2D1_BITMAP_PROPERTIES1
*desc
, struct d2d_bitmap
**bitmap
)
525 D2D1_BITMAP_PROPERTIES1 d
;
527 if (IsEqualGUID(iid
, &IID_ID2D1Bitmap
))
529 struct d2d_bitmap
*src_impl
= unsafe_impl_from_ID2D1Bitmap(data
);
530 ID3D11Device
*device
;
533 if (src_impl
->factory
!= context
->factory
)
535 hr
= D2DERR_WRONG_FACTORY
;
539 ID3D11Resource_GetDevice(src_impl
->resource
, &device
);
540 ID3D11Device_Release(device
);
541 if (device
!= (ID3D11Device
*)context
->d3d_device
)
543 hr
= D2DERR_UNSUPPORTED_OPERATION
;
550 if (d
.pixelFormat
.format
== DXGI_FORMAT_UNKNOWN
)
551 d
.pixelFormat
.format
= src_impl
->format
.format
;
552 if (d
.pixelFormat
.alphaMode
== D2D1_ALPHA_MODE_UNKNOWN
)
553 d
.pixelFormat
.alphaMode
= src_impl
->format
.alphaMode
;
557 d
.pixelFormat
= src_impl
->format
;
558 d
.dpiX
= src_impl
->dpi_x
;
559 d
.dpiY
= src_impl
->dpi_y
;
560 d
.bitmapOptions
= src_impl
->options
;
561 d
.colorContext
= NULL
;
565 if (!format_supported(&desc
->pixelFormat
))
567 WARN("Tried to create bitmap with unsupported format {%#x / %#x}.\n",
568 desc
->pixelFormat
.format
, desc
->pixelFormat
.alphaMode
);
569 hr
= D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
573 if (!(*bitmap
= calloc(1, sizeof(**bitmap
))))
579 d2d_bitmap_init(*bitmap
, context
, src_impl
->resource
, src_impl
->pixel_size
, desc
);
580 TRACE("Created bitmap %p.\n", *bitmap
);
586 if (IsEqualGUID(iid
, &IID_IDXGISurface
) || IsEqualGUID(iid
, &IID_IDXGISurface1
))
588 DXGI_SURFACE_DESC surface_desc
;
589 IDXGISurface
*surface
= data
;
590 ID3D11Resource
*resource
;
591 D2D1_SIZE_U pixel_size
;
592 ID3D11Device
*device
;
595 if (FAILED(IDXGISurface_QueryInterface(surface
, &IID_ID3D11Resource
, (void **)&resource
)))
597 WARN("Failed to get d3d resource from dxgi surface.\n");
601 ID3D11Resource_GetDevice(resource
, &device
);
602 ID3D11Device_Release(device
);
603 if (device
!= (ID3D11Device
*)context
->d3d_device
)
605 ID3D11Resource_Release(resource
);
606 return D2DERR_UNSUPPORTED_OPERATION
;
609 if (!(*bitmap
= calloc(1, sizeof(**bitmap
))))
611 ID3D11Resource_Release(resource
);
612 return E_OUTOFMEMORY
;
616 if (FAILED(hr
= IDXGISurface_GetDesc(surface
, &surface_desc
)))
618 WARN("Failed to get surface desc, hr %#lx.\n", hr
);
619 ID3D11Resource_Release(resource
);
625 memset(&d
, 0, sizeof(d
));
626 d
.pixelFormat
.format
= surface_desc
.Format
;
627 d
.bitmapOptions
= d2d_get_bitmap_options_for_surface(surface
);
632 if (d
.pixelFormat
.format
== DXGI_FORMAT_UNKNOWN
)
633 d
.pixelFormat
.format
= surface_desc
.Format
;
636 if (d
.dpiX
== 0.0f
|| d
.dpiY
== 0.0f
)
639 d
.dpiX
= context
->desc
.dpiX
;
641 d
.dpiY
= context
->desc
.dpiY
;
644 pixel_size
.width
= surface_desc
.Width
;
645 pixel_size
.height
= surface_desc
.Height
;
647 d2d_bitmap_init(*bitmap
, context
, resource
, pixel_size
, &d
);
648 ID3D11Resource_Release(resource
);
649 TRACE("Created bitmap %p.\n", *bitmap
);
654 WARN("Unhandled interface %s.\n", debugstr_guid(iid
));
659 HRESULT
d2d_bitmap_create_from_wic_bitmap(struct d2d_device_context
*context
, IWICBitmapSource
*bitmap_source
,
660 const D2D1_BITMAP_PROPERTIES1
*desc
, struct d2d_bitmap
**bitmap
)
662 const D2D1_PIXEL_FORMAT
*d2d_format
;
663 D2D1_BITMAP_PROPERTIES1 bitmap_desc
;
664 WICPixelFormatGUID wic_format
;
665 unsigned int bpp
, data_size
;
675 const WICPixelFormatGUID
*wic
;
676 D2D1_PIXEL_FORMAT d2d
;
680 {&GUID_WICPixelFormat32bppPBGRA
, {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
}},
681 {&GUID_WICPixelFormat32bppPRGBA
, {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_PREMULTIPLIED
}},
682 {&GUID_WICPixelFormat32bppBGR
, {DXGI_FORMAT_B8G8R8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
}},
683 {&GUID_WICPixelFormat32bppRGB
, {DXGI_FORMAT_R8G8B8A8_UNORM
, D2D1_ALPHA_MODE_IGNORE
}},
686 if (FAILED(hr
= IWICBitmapSource_GetSize(bitmap_source
, &size
.width
, &size
.height
)))
688 WARN("Failed to get bitmap size, hr %#lx.\n", hr
);
694 bitmap_desc
.pixelFormat
.format
= DXGI_FORMAT_UNKNOWN
;
695 bitmap_desc
.pixelFormat
.alphaMode
= D2D1_ALPHA_MODE_UNKNOWN
;
696 bitmap_desc
.dpiX
= 0.0f
;
697 bitmap_desc
.dpiY
= 0.0f
;
698 bitmap_desc
.bitmapOptions
= 0;
699 bitmap_desc
.colorContext
= NULL
;
706 if (FAILED(hr
= IWICBitmapSource_GetPixelFormat(bitmap_source
, &wic_format
)))
708 WARN("Failed to get bitmap format, hr %#lx.\n", hr
);
712 for (i
= 0, d2d_format
= NULL
; i
< ARRAY_SIZE(format_lookup
); ++i
)
714 if (IsEqualGUID(&wic_format
, format_lookup
[i
].wic
))
716 d2d_format
= &format_lookup
[i
].d2d
;
723 WARN("Unsupported WIC bitmap format %s.\n", debugstr_guid(&wic_format
));
724 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
727 if (bitmap_desc
.pixelFormat
.format
== DXGI_FORMAT_UNKNOWN
)
728 bitmap_desc
.pixelFormat
.format
= d2d_format
->format
;
729 if (bitmap_desc
.pixelFormat
.alphaMode
== D2D1_ALPHA_MODE_UNKNOWN
)
730 bitmap_desc
.pixelFormat
.alphaMode
= d2d_format
->alphaMode
;
732 switch (bitmap_desc
.pixelFormat
.format
)
734 case DXGI_FORMAT_B8G8R8A8_UNORM
:
735 case DXGI_FORMAT_R8G8B8A8_UNORM
:
740 FIXME("Unhandled format %#x.\n", bitmap_desc
.pixelFormat
.format
);
741 return D2DERR_UNSUPPORTED_PIXEL_FORMAT
;
744 pitch
= ((bpp
* size
.width
) + 15) & ~15;
745 if (pitch
/ bpp
< size
.width
)
746 return E_OUTOFMEMORY
;
747 if (!(data
= calloc(size
.height
, pitch
)))
748 return E_OUTOFMEMORY
;
749 data_size
= size
.height
* pitch
;
753 rect
.Width
= size
.width
;
754 rect
.Height
= size
.height
;
755 if (FAILED(hr
= IWICBitmapSource_CopyPixels(bitmap_source
, &rect
, pitch
, data_size
, data
)))
757 WARN("Failed to copy bitmap pixels, hr %#lx.\n", hr
);
762 hr
= d2d_bitmap_create(context
, size
, data
, pitch
, &bitmap_desc
, bitmap
);
769 struct d2d_bitmap
*unsafe_impl_from_ID2D1Bitmap(ID2D1Bitmap
*iface
)
773 assert(iface
->lpVtbl
== (ID2D1BitmapVtbl
*)&d2d_bitmap_vtbl
);
774 return CONTAINING_RECORD(iface
, struct d2d_bitmap
, ID2D1Bitmap1_iface
);