mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / d2d1 / factory.c
blobb65727d3a32766f61bc289baf13579606653ee8a
1 /*
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 #define D2D1_INIT_GUID
20 #include "d2d1_private.h"
22 WINE_DECLARE_DEBUG_CHANNEL(winediag);
23 WINE_DEFAULT_DEBUG_CHANNEL(d2d);
25 struct d2d_settings d2d_settings =
27 ~0u, /* No ID2D1Factory version limit by default. */
30 struct d2d_factory
32 ID2D1Factory2 ID2D1Factory2_iface;
33 ID2D1Multithread ID2D1Multithread_iface;
34 LONG refcount;
36 ID3D10Device1 *device;
38 float dpi_x;
39 float dpi_y;
41 CRITICAL_SECTION cs;
44 static inline struct d2d_factory *impl_from_ID2D1Factory2(ID2D1Factory2 *iface)
46 return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Factory2_iface);
49 static inline struct d2d_factory *impl_from_ID2D1Multithread(ID2D1Multithread *iface)
51 return CONTAINING_RECORD(iface, struct d2d_factory, ID2D1Multithread_iface);
54 static HRESULT d2d_factory_reload_sysmetrics(struct d2d_factory *factory)
56 HDC hdc;
58 if (!(hdc = GetDC(NULL)))
60 factory->dpi_x = factory->dpi_y = 96.0f;
61 return E_FAIL;
64 factory->dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
65 factory->dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
67 ReleaseDC(NULL, hdc);
69 return S_OK;
72 static HRESULT STDMETHODCALLTYPE d2d_factory_QueryInterface(ID2D1Factory2 *iface, REFIID iid, void **out)
74 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
76 TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
78 if ((IsEqualGUID(iid, &IID_ID2D1Factory2) && d2d_settings.max_version_factory >= 2)
79 || (IsEqualGUID(iid, &IID_ID2D1Factory1) && d2d_settings.max_version_factory >= 1)
80 || IsEqualGUID(iid, &IID_ID2D1Factory)
81 || IsEqualGUID(iid, &IID_IUnknown))
83 ID2D1Factory2_AddRef(iface);
84 *out = iface;
85 return S_OK;
87 else if (IsEqualGUID(iid, &IID_ID2D1Multithread))
89 ID2D1Factory2_AddRef(iface);
90 *out = &factory->ID2D1Multithread_iface;
91 return S_OK;
94 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
96 *out = NULL;
97 return E_NOINTERFACE;
100 static ULONG STDMETHODCALLTYPE d2d_factory_AddRef(ID2D1Factory2 *iface)
102 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
103 ULONG refcount = InterlockedIncrement(&factory->refcount);
105 TRACE("%p increasing refcount to %u.\n", iface, refcount);
107 return refcount;
110 static ULONG STDMETHODCALLTYPE d2d_factory_Release(ID2D1Factory2 *iface)
112 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
113 ULONG refcount = InterlockedDecrement(&factory->refcount);
115 TRACE("%p decreasing refcount to %u.\n", iface, refcount);
117 if (!refcount)
119 if (factory->device)
120 ID3D10Device1_Release(factory->device);
121 DeleteCriticalSection(&factory->cs);
122 heap_free(factory);
125 return refcount;
128 static HRESULT STDMETHODCALLTYPE d2d_factory_ReloadSystemMetrics(ID2D1Factory2 *iface)
130 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
132 TRACE("iface %p.\n", iface);
134 return d2d_factory_reload_sysmetrics(factory);
137 static void STDMETHODCALLTYPE d2d_factory_GetDesktopDpi(ID2D1Factory2 *iface, float *dpi_x, float *dpi_y)
139 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
141 TRACE("iface %p, dpi_x %p, dpi_y %p.\n", iface, dpi_x, dpi_y);
143 *dpi_x = factory->dpi_x;
144 *dpi_y = factory->dpi_y;
147 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRectangleGeometry(ID2D1Factory2 *iface,
148 const D2D1_RECT_F *rect, ID2D1RectangleGeometry **geometry)
150 struct d2d_geometry *object;
151 HRESULT hr;
153 TRACE("iface %p, rect %s, geometry %p.\n", iface, debug_d2d_rect_f(rect), geometry);
155 if (!(object = heap_alloc_zero(sizeof(*object))))
156 return E_OUTOFMEMORY;
158 if (FAILED(hr = d2d_rectangle_geometry_init(object, (ID2D1Factory *)iface, rect)))
160 WARN("Failed to initialize rectangle geometry, hr %#x.\n", hr);
161 heap_free(object);
162 return hr;
165 TRACE("Created rectangle geometry %p.\n", object);
166 *geometry = (ID2D1RectangleGeometry *)&object->ID2D1Geometry_iface;
168 return S_OK;
171 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateRoundedRectangleGeometry(ID2D1Factory2 *iface,
172 const D2D1_ROUNDED_RECT *rounded_rect, ID2D1RoundedRectangleGeometry **geometry)
174 struct d2d_geometry *object;
175 HRESULT hr;
177 TRACE("iface %p, rounded_rect %s, geometry %p.\n", iface, debug_d2d_rounded_rect(rounded_rect), geometry);
179 if (!(object = heap_alloc_zero(sizeof(*object))))
180 return E_OUTOFMEMORY;
182 if (FAILED(hr = d2d_rounded_rectangle_geometry_init(object, (ID2D1Factory *)iface, rounded_rect)))
184 WARN("Failed to initialize rounded rectangle geometry, hr %#x.\n", hr);
185 heap_free(object);
186 return hr;
189 TRACE("Created rounded rectangle geometry %p.\n", object);
190 *geometry = (ID2D1RoundedRectangleGeometry *)&object->ID2D1Geometry_iface;
192 return S_OK;
195 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateEllipseGeometry(ID2D1Factory2 *iface,
196 const D2D1_ELLIPSE *ellipse, ID2D1EllipseGeometry **geometry)
198 struct d2d_geometry *object;
199 HRESULT hr;
201 TRACE("iface %p, ellipse %s, geometry %p.\n", iface, debug_d2d_ellipse(ellipse), geometry);
203 if (!(object = heap_alloc_zero(sizeof(*object))))
204 return E_OUTOFMEMORY;
206 if (FAILED(hr = d2d_ellipse_geometry_init(object, (ID2D1Factory *)iface, ellipse)))
208 WARN("Failed to initialize ellipse geometry, hr %#x.\n", hr);
209 heap_free(object);
210 return hr;
213 TRACE("Created ellipse geometry %p.\n", object);
214 *geometry = (ID2D1EllipseGeometry *)&object->ID2D1Geometry_iface;
216 return S_OK;
219 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateGeometryGroup(ID2D1Factory2 *iface,
220 D2D1_FILL_MODE fill_mode, ID2D1Geometry **geometries, UINT32 geometry_count, ID2D1GeometryGroup **group)
222 struct d2d_geometry *object;
223 HRESULT hr;
225 TRACE("iface %p, fill_mode %#x, geometries %p, geometry_count %u, group %p.\n",
226 iface, fill_mode, geometries, geometry_count, group);
228 if (!(object = heap_alloc_zero(sizeof(*object))))
229 return E_OUTOFMEMORY;
231 if (FAILED(hr = d2d_geometry_group_init(object, (ID2D1Factory *)iface, fill_mode, geometries, geometry_count)))
233 WARN("Failed to initialize geometry group, hr %#x.\n", hr);
234 heap_free(object);
235 return hr;
238 TRACE("Created geometry group %p.\n", object);
239 *group = (ID2D1GeometryGroup *)&object->ID2D1Geometry_iface;
241 return S_OK;
244 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateTransformedGeometry(ID2D1Factory2 *iface,
245 ID2D1Geometry *src_geometry, const D2D1_MATRIX_3X2_F *transform,
246 ID2D1TransformedGeometry **transformed_geometry)
248 struct d2d_geometry *object;
250 TRACE("iface %p, src_geometry %p, transform %p, transformed_geometry %p.\n",
251 iface, src_geometry, transform, transformed_geometry);
253 if (!(object = heap_alloc_zero(sizeof(*object))))
254 return E_OUTOFMEMORY;
256 d2d_transformed_geometry_init(object, (ID2D1Factory *)iface, src_geometry, transform);
258 TRACE("Created transformed geometry %p.\n", object);
259 *transformed_geometry = (ID2D1TransformedGeometry *)&object->ID2D1Geometry_iface;
261 return S_OK;
264 static HRESULT STDMETHODCALLTYPE d2d_factory_CreatePathGeometry(ID2D1Factory2 *iface, ID2D1PathGeometry **geometry)
266 struct d2d_geometry *object;
268 TRACE("iface %p, geometry %p.\n", iface, geometry);
270 if (!(object = heap_alloc_zero(sizeof(*object))))
271 return E_OUTOFMEMORY;
273 d2d_path_geometry_init(object, (ID2D1Factory *)iface);
275 TRACE("Created path geometry %p.\n", object);
276 *geometry = (ID2D1PathGeometry *)&object->ID2D1Geometry_iface;
278 return S_OK;
281 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateStrokeStyle(ID2D1Factory2 *iface,
282 const D2D1_STROKE_STYLE_PROPERTIES *desc, const float *dashes, UINT32 dash_count,
283 ID2D1StrokeStyle **stroke_style)
285 struct d2d_stroke_style *object;
286 HRESULT hr;
288 TRACE("iface %p, desc %p, dashes %p, dash_count %u, stroke_style %p.\n",
289 iface, desc, dashes, dash_count, stroke_style);
291 if (!(object = heap_alloc_zero(sizeof(*object))))
292 return E_OUTOFMEMORY;
294 if (FAILED(hr = d2d_stroke_style_init(object, (ID2D1Factory *)iface, desc, dashes, dash_count)))
296 WARN("Failed to initialize stroke style, hr %#x.\n", hr);
297 heap_free(object);
298 return hr;
301 TRACE("Created stroke style %p.\n", object);
302 *stroke_style = &object->ID2D1StrokeStyle_iface;
304 return S_OK;
307 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDrawingStateBlock(ID2D1Factory2 *iface,
308 const D2D1_DRAWING_STATE_DESCRIPTION *desc, IDWriteRenderingParams *text_rendering_params,
309 ID2D1DrawingStateBlock **state_block)
311 D2D1_DRAWING_STATE_DESCRIPTION1 state_desc;
312 struct d2d_state_block *object;
314 TRACE("iface %p, desc %p, text_rendering_params %p, state_block %p.\n",
315 iface, desc, text_rendering_params, state_block);
317 if (!(object = heap_alloc_zero(sizeof(*object))))
318 return E_OUTOFMEMORY;
320 if (desc)
322 memcpy(&state_desc, desc, sizeof(*desc));
323 state_desc.primitiveBlend = D2D1_PRIMITIVE_BLEND_SOURCE_OVER;
324 state_desc.unitMode = D2D1_UNIT_MODE_DIPS;
327 d2d_state_block_init(object, (ID2D1Factory *)iface, desc ? &state_desc : NULL, text_rendering_params);
329 TRACE("Created state block %p.\n", object);
330 *state_block = (ID2D1DrawingStateBlock *)&object->ID2D1DrawingStateBlock1_iface;
332 return S_OK;
335 static HRESULT d2d_factory_get_device(struct d2d_factory *factory, ID3D10Device1 **device)
337 HRESULT hr = S_OK;
339 if (!factory->device && FAILED(hr = D3D10CreateDevice1(NULL, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT,
340 D3D10_FEATURE_LEVEL_10_0, D3D10_1_SDK_VERSION, &factory->device)))
341 WARN("Failed to create device, hr %#x.\n", hr);
343 *device = factory->device;
344 return hr;
347 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateWicBitmapRenderTarget(ID2D1Factory2 *iface,
348 IWICBitmap *target, const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
350 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
351 struct d2d_wic_render_target *object;
352 ID3D10Device1 *device;
353 HRESULT hr;
355 TRACE("iface %p, target %p, desc %p, render_target %p.\n", iface, target, desc, render_target);
357 if (!(object = heap_alloc_zero(sizeof(*object))))
358 return E_OUTOFMEMORY;
360 if (FAILED(hr = d2d_factory_get_device(factory, &device)))
362 heap_free(object);
363 return hr;
366 if (FAILED(hr = d2d_wic_render_target_init(object, (ID2D1Factory1 *)iface, device, target, desc)))
368 WARN("Failed to initialize render target, hr %#x.\n", hr);
369 heap_free(object);
370 return hr;
373 TRACE("Created render target %p.\n", object);
374 *render_target = object->dxgi_target;
376 return S_OK;
379 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateHwndRenderTarget(ID2D1Factory2 *iface,
380 const D2D1_RENDER_TARGET_PROPERTIES *desc, const D2D1_HWND_RENDER_TARGET_PROPERTIES *hwnd_rt_desc,
381 ID2D1HwndRenderTarget **render_target)
383 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
384 struct d2d_hwnd_render_target *object;
385 ID3D10Device1 *device;
386 HRESULT hr;
388 TRACE("iface %p, desc %p, hwnd_rt_desc %p, render_target %p.\n", iface, desc, hwnd_rt_desc, render_target);
390 if (FAILED(hr = d2d_factory_get_device(factory, &device)))
391 return hr;
393 if (!(object = heap_alloc_zero(sizeof(*object))))
394 return E_OUTOFMEMORY;
396 if (FAILED(hr = d2d_hwnd_render_target_init(object, (ID2D1Factory1 *)iface, device, desc, hwnd_rt_desc)))
398 WARN("Failed to initialize render target, hr %#x.\n", hr);
399 heap_free(object);
400 return hr;
403 TRACE("Created render target %p.\n", object);
404 *render_target = &object->ID2D1HwndRenderTarget_iface;
406 return S_OK;
409 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDxgiSurfaceRenderTarget(ID2D1Factory2 *iface,
410 IDXGISurface *surface, const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1RenderTarget **render_target)
412 IDXGIDevice *dxgi_device;
413 ID2D1Device *device;
414 HRESULT hr;
416 TRACE("iface %p, surface %p, desc %p, render_target %p.\n", iface, surface, desc, render_target);
418 if (FAILED(hr = IDXGISurface_GetDevice(surface, &IID_IDXGIDevice, (void **)&dxgi_device)))
420 WARN("Failed to get DXGI device, hr %#x.\n", hr);
421 return hr;
424 hr = ID2D1Factory1_CreateDevice((ID2D1Factory1 *)iface, dxgi_device, &device);
425 IDXGIDevice_Release(dxgi_device);
426 if (FAILED(hr))
428 WARN("Failed to create D2D device, hr %#x.\n", hr);
429 return hr;
432 hr = d2d_d3d_create_render_target(device, surface, NULL, NULL, desc, (void **)render_target);
433 ID2D1Device_Release(device);
434 return hr;
437 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDCRenderTarget(ID2D1Factory2 *iface,
438 const D2D1_RENDER_TARGET_PROPERTIES *desc, ID2D1DCRenderTarget **render_target)
440 struct d2d_factory *factory = impl_from_ID2D1Factory2(iface);
441 struct d2d_dc_render_target *object;
442 ID3D10Device1 *device;
443 HRESULT hr;
445 TRACE("iface %p, desc %p, render_target %p.\n", iface, desc, render_target);
447 if (FAILED(hr = d2d_factory_get_device(factory, &device)))
448 return hr;
450 if (!(object = heap_alloc_zero(sizeof(*object))))
451 return E_OUTOFMEMORY;
453 if (FAILED(hr = d2d_dc_render_target_init(object, (ID2D1Factory1 *)iface, device, desc)))
455 WARN("Failed to initialize render target, hr %#x.\n", hr);
456 heap_free(object);
457 return hr;
460 TRACE("Created render target %p.\n", object);
461 *render_target = &object->ID2D1DCRenderTarget_iface;
463 return S_OK;
466 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDevice(ID2D1Factory2 *iface,
467 IDXGIDevice *dxgi_device, ID2D1Device **device)
469 struct d2d_device *object;
471 TRACE("iface %p, dxgi_device %p, device %p.\n", iface, dxgi_device, device);
473 if (!(object = heap_alloc_zero(sizeof(*object))))
474 return E_OUTOFMEMORY;
476 d2d_device_init(object, (ID2D1Factory1 *)iface, dxgi_device);
478 TRACE("Create device %p.\n", object);
479 *device = &object->ID2D1Device_iface;
481 return S_OK;
484 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateStrokeStyle1(ID2D1Factory2 *iface,
485 const D2D1_STROKE_STYLE_PROPERTIES1 *desc, const float *dashes, UINT32 dash_count,
486 ID2D1StrokeStyle1 **stroke_style)
488 FIXME("iface %p, desc %p, dashes %p, dash_count %u, stroke_style %p stub!\n",
489 iface, desc, dashes, dash_count, stroke_style);
491 return E_NOTIMPL;
494 static HRESULT STDMETHODCALLTYPE d2d_factory_CreatePathGeometry1(ID2D1Factory2 *iface, ID2D1PathGeometry1 **geometry)
496 FIXME("iface %p, geometry %p stub!\n", iface, geometry);
498 return E_NOTIMPL;
501 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDrawingStateBlock1(ID2D1Factory2 *iface,
502 const D2D1_DRAWING_STATE_DESCRIPTION1 *desc, IDWriteRenderingParams *text_rendering_params,
503 ID2D1DrawingStateBlock1 **state_block)
505 struct d2d_state_block *object;
507 TRACE("iface %p, desc %p, text_rendering_params %p, state_block %p.\n",
508 iface, desc, text_rendering_params, state_block);
510 if (!(object = heap_alloc_zero(sizeof(*object))))
511 return E_OUTOFMEMORY;
513 d2d_state_block_init(object, (ID2D1Factory *)iface, desc, text_rendering_params);
515 TRACE("Created state block %p.\n", object);
516 *state_block = &object->ID2D1DrawingStateBlock1_iface;
518 return S_OK;
521 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateGdiMetafile(ID2D1Factory2 *iface,
522 IStream *stream, ID2D1GdiMetafile **metafile)
524 FIXME("iface %p, stream %p, metafile %p stub!\n", iface, stream, metafile);
526 return E_NOTIMPL;
529 static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromStream(ID2D1Factory2 *iface,
530 REFCLSID effect_id, IStream *property_xml, const D2D1_PROPERTY_BINDING *bindings,
531 UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory)
533 FIXME("iface %p, effect_id %s, property_xml %p, bindings %p, binding_count %u, effect_factory %p stub!\n",
534 iface, debugstr_guid(effect_id), property_xml, bindings, binding_count, effect_factory);
536 return E_NOTIMPL;
539 static HRESULT STDMETHODCALLTYPE d2d_factory_RegisterEffectFromString(ID2D1Factory2 *iface,
540 REFCLSID effect_id, const WCHAR *property_xml, const D2D1_PROPERTY_BINDING *bindings,
541 UINT32 binding_count, PD2D1_EFFECT_FACTORY effect_factory)
543 FIXME("iface %p, effect_id %s, property_xml %s, bindings %p, binding_count %u, effect_factory %p stub!\n",
544 iface, debugstr_guid(effect_id), debugstr_w(property_xml), bindings, binding_count, effect_factory);
546 return S_OK;
549 static HRESULT STDMETHODCALLTYPE d2d_factory_UnregisterEffect(ID2D1Factory2 *iface, REFCLSID effect_id)
551 FIXME("iface %p, effect_id %s stub!\n", iface, debugstr_guid(effect_id));
553 return E_NOTIMPL;
556 static HRESULT STDMETHODCALLTYPE d2d_factory_GetRegisteredEffects(ID2D1Factory2 *iface,
557 CLSID *effects, UINT32 effect_count, UINT32 *returned, UINT32 *registered)
559 FIXME("iface %p, effects %p, effect_count %u, returned %p, registered %p stub!\n",
560 iface, effects, effect_count, returned, registered);
562 return E_NOTIMPL;
565 static HRESULT STDMETHODCALLTYPE d2d_factory_GetEffectProperties(ID2D1Factory2 *iface,
566 REFCLSID effect_id, ID2D1Properties **props)
568 FIXME("iface %p, effect_id %s, props %p stub!\n", iface, debugstr_guid(effect_id), props);
570 return E_NOTIMPL;
573 static HRESULT STDMETHODCALLTYPE d2d_factory_ID2D1Factory1_CreateDevice(ID2D1Factory2 *iface, IDXGIDevice *dxgi_device,
574 ID2D1Device1 **device)
576 FIXME("iface %p, dxgi_device %p, device %p stub!\n", iface, dxgi_device, device);
578 return E_NOTIMPL;
581 static const struct ID2D1Factory2Vtbl d2d_factory_vtbl =
583 d2d_factory_QueryInterface,
584 d2d_factory_AddRef,
585 d2d_factory_Release,
586 d2d_factory_ReloadSystemMetrics,
587 d2d_factory_GetDesktopDpi,
588 d2d_factory_CreateRectangleGeometry,
589 d2d_factory_CreateRoundedRectangleGeometry,
590 d2d_factory_CreateEllipseGeometry,
591 d2d_factory_CreateGeometryGroup,
592 d2d_factory_CreateTransformedGeometry,
593 d2d_factory_CreatePathGeometry,
594 d2d_factory_CreateStrokeStyle,
595 d2d_factory_CreateDrawingStateBlock,
596 d2d_factory_CreateWicBitmapRenderTarget,
597 d2d_factory_CreateHwndRenderTarget,
598 d2d_factory_CreateDxgiSurfaceRenderTarget,
599 d2d_factory_CreateDCRenderTarget,
600 d2d_factory_CreateDevice,
601 d2d_factory_CreateStrokeStyle1,
602 d2d_factory_CreatePathGeometry1,
603 d2d_factory_CreateDrawingStateBlock1,
604 d2d_factory_CreateGdiMetafile,
605 d2d_factory_RegisterEffectFromStream,
606 d2d_factory_RegisterEffectFromString,
607 d2d_factory_UnregisterEffect,
608 d2d_factory_GetRegisteredEffects,
609 d2d_factory_GetEffectProperties,
610 d2d_factory_ID2D1Factory1_CreateDevice,
613 static HRESULT STDMETHODCALLTYPE d2d_factory_mt_QueryInterface(ID2D1Multithread *iface, REFIID iid, void **out)
615 struct d2d_factory *factory = impl_from_ID2D1Multithread(iface);
616 return d2d_factory_QueryInterface(&factory->ID2D1Factory2_iface, iid, out);
619 static ULONG STDMETHODCALLTYPE d2d_factory_mt_AddRef(ID2D1Multithread *iface)
621 struct d2d_factory *factory = impl_from_ID2D1Multithread(iface);
622 return d2d_factory_AddRef(&factory->ID2D1Factory2_iface);
625 static ULONG STDMETHODCALLTYPE d2d_factory_mt_Release(ID2D1Multithread *iface)
627 struct d2d_factory *factory = impl_from_ID2D1Multithread(iface);
628 return d2d_factory_Release(&factory->ID2D1Factory2_iface);
631 static BOOL STDMETHODCALLTYPE d2d_factory_mt_GetMultithreadProtected(ID2D1Multithread *iface)
633 return TRUE;
636 static void STDMETHODCALLTYPE d2d_factory_mt_Enter(ID2D1Multithread *iface)
638 struct d2d_factory *factory = impl_from_ID2D1Multithread(iface);
640 TRACE("%p.\n", iface);
642 return EnterCriticalSection(&factory->cs);
645 static void STDMETHODCALLTYPE d2d_factory_mt_Leave(ID2D1Multithread *iface)
647 struct d2d_factory *factory = impl_from_ID2D1Multithread(iface);
649 TRACE("%p.\n", iface);
651 return LeaveCriticalSection(&factory->cs);
654 static BOOL STDMETHODCALLTYPE d2d_factory_st_GetMultithreadProtected(ID2D1Multithread *iface)
656 return FALSE;
659 static void STDMETHODCALLTYPE d2d_factory_st_Enter(ID2D1Multithread *iface)
663 static void STDMETHODCALLTYPE d2d_factory_st_Leave(ID2D1Multithread *iface)
667 static const struct ID2D1MultithreadVtbl d2d_factory_multithread_vtbl =
669 d2d_factory_mt_QueryInterface,
670 d2d_factory_mt_AddRef,
671 d2d_factory_mt_Release,
672 d2d_factory_mt_GetMultithreadProtected,
673 d2d_factory_mt_Enter,
674 d2d_factory_mt_Leave,
677 static const struct ID2D1MultithreadVtbl d2d_factory_multithread_noop_vtbl =
679 d2d_factory_mt_QueryInterface,
680 d2d_factory_mt_AddRef,
681 d2d_factory_mt_Release,
682 d2d_factory_st_GetMultithreadProtected,
683 d2d_factory_st_Enter,
684 d2d_factory_st_Leave,
687 static void d2d_factory_init(struct d2d_factory *factory, D2D1_FACTORY_TYPE factory_type,
688 const D2D1_FACTORY_OPTIONS *factory_options)
690 if (factory_options && factory_options->debugLevel != D2D1_DEBUG_LEVEL_NONE)
691 WARN("Ignoring debug level %#x.\n", factory_options->debugLevel);
693 factory->ID2D1Factory2_iface.lpVtbl = &d2d_factory_vtbl;
694 factory->ID2D1Multithread_iface.lpVtbl = factory_type == D2D1_FACTORY_TYPE_SINGLE_THREADED ?
695 &d2d_factory_multithread_noop_vtbl : &d2d_factory_multithread_vtbl;
696 factory->refcount = 1;
697 d2d_factory_reload_sysmetrics(factory);
698 InitializeCriticalSection(&factory->cs);
701 HRESULT WINAPI D2D1CreateFactory(D2D1_FACTORY_TYPE factory_type, REFIID iid,
702 const D2D1_FACTORY_OPTIONS *factory_options, void **factory)
704 struct d2d_factory *object;
705 HRESULT hr;
707 TRACE("factory_type %#x, iid %s, factory_options %p, factory %p.\n",
708 factory_type, debugstr_guid(iid), factory_options, factory);
710 if (factory_type != D2D1_FACTORY_TYPE_SINGLE_THREADED &&
711 factory_type != D2D1_FACTORY_TYPE_MULTI_THREADED)
713 return E_INVALIDARG;
716 if (!(object = heap_alloc_zero(sizeof(*object))))
717 return E_OUTOFMEMORY;
719 d2d_factory_init(object, factory_type, factory_options);
721 TRACE("Created factory %p.\n", object);
723 hr = ID2D1Factory2_QueryInterface(&object->ID2D1Factory2_iface, iid, factory);
724 ID2D1Factory2_Release(&object->ID2D1Factory2_iface);
726 return hr;
729 void WINAPI D2D1MakeRotateMatrix(float angle, D2D1_POINT_2F center, D2D1_MATRIX_3X2_F *matrix)
731 float theta, sin_theta, cos_theta;
733 TRACE("angle %.8e, center %s, matrix %p.\n", angle, debug_d2d_point_2f(&center), matrix);
735 theta = angle * (M_PI / 180.0f);
736 sin_theta = sinf(theta);
737 cos_theta = cosf(theta);
739 /* translate(center) * rotate(theta) * translate(-center) */
740 matrix->_11 = cos_theta;
741 matrix->_12 = sin_theta;
742 matrix->_21 = -sin_theta;
743 matrix->_22 = cos_theta;
744 matrix->_31 = center.x - center.x * cos_theta + center.y * sin_theta;
745 matrix->_32 = center.y - center.x * sin_theta - center.y * cos_theta;
748 void WINAPI D2D1MakeSkewMatrix(float angle_x, float angle_y, D2D1_POINT_2F center, D2D1_MATRIX_3X2_F *matrix)
750 float tan_x, tan_y;
752 TRACE("angle_x %.8e, angle_y %.8e, center %s, matrix %p.\n", angle_x, angle_y, debug_d2d_point_2f(&center), matrix);
754 tan_x = tan(angle_x * (M_PI / 180.0f));
755 tan_y = tan(angle_y * (M_PI / 180.0f));
757 /* translate(-center) * skew() * translate(center) */
758 matrix->_11 = 1.0f;
759 matrix->_12 = tan_y;
760 matrix->_21 = tan_x;
761 matrix->_22 = 1.0f;
762 matrix->_31 = -tan_x * center.y;
763 matrix->_32 = -tan_y * center.x;
766 BOOL WINAPI D2D1IsMatrixInvertible(const D2D1_MATRIX_3X2_F *matrix)
768 TRACE("matrix %p.\n", matrix);
770 return (matrix->_11 * matrix->_22 - matrix->_21 * matrix->_12) != 0.0f;
773 BOOL WINAPI D2D1InvertMatrix(D2D1_MATRIX_3X2_F *matrix)
775 D2D1_MATRIX_3X2_F m = *matrix;
777 TRACE("matrix %p.\n", matrix);
779 return d2d_matrix_invert(matrix, &m);
782 HRESULT WINAPI D2D1CreateDevice(IDXGIDevice *dxgi_device,
783 const D2D1_CREATION_PROPERTIES *properties, ID2D1Device **device)
785 D2D1_CREATION_PROPERTIES default_properties = {0};
786 D2D1_FACTORY_OPTIONS factory_options;
787 ID3D11Device *d3d_device;
788 ID2D1Factory1 *factory;
789 HRESULT hr;
791 TRACE("dxgi_device %p, properties %p, device %p.\n", dxgi_device, properties, device);
793 if (!properties)
795 if (SUCCEEDED(IDXGIDevice_QueryInterface(dxgi_device, &IID_ID3D11Device, (void **)&d3d_device)))
797 if (!(ID3D11Device_GetCreationFlags(d3d_device) & D3D11_CREATE_DEVICE_SINGLETHREADED))
798 default_properties.threadingMode = D2D1_THREADING_MODE_MULTI_THREADED;
799 ID3D11Device_Release(d3d_device);
801 properties = &default_properties;
804 factory_options.debugLevel = properties->debugLevel;
805 if (FAILED(hr = D2D1CreateFactory(properties->threadingMode,
806 &IID_ID2D1Factory1, &factory_options, (void **)&factory)))
807 return hr;
809 hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, device);
810 ID2D1Factory1_Release(factory);
811 return hr;
814 void WINAPI D2D1SinCos(float angle, float *s, float *c)
816 TRACE("angle %.8e, s %p, c %p.\n", angle, s, c);
818 *s = sinf(angle);
819 *c = cosf(angle);
822 float WINAPI D2D1Tan(float angle)
824 TRACE("angle %.8e.\n", angle);
826 return tanf(angle);
829 float WINAPI D2D1Vec3Length(float x, float y, float z)
831 TRACE("x %.8e, y %.8e, z %.8e.\n", x, y, z);
833 return sqrtf(x * x + y * y + z * z);
836 /* See IEC 61966-2-1:1999; also described in the EXT_texture_sRGB OpenGL
837 * extension, among others. */
838 static float srgb_transfer_function(float x)
840 if (x <= 0.0f)
841 return 0.0f;
842 else if (x >= 1.0f)
843 return 1.0f;
844 else if (x <= 0.0031308f)
845 return 12.92f * x;
846 else
847 return 1.055f * powf(x, 1.0f / 2.4f) - 0.055f;
850 static float srgb_inverse_transfer_function(float x)
852 if (x <= 0.0f)
853 return 0.0f;
854 else if (x >= 1.0f)
855 return 1.0f;
856 else if (x <= 0.04045f)
857 return x / 12.92f;
858 else
859 return powf((x + 0.055f) / 1.055f, 2.4f);
862 D2D1_COLOR_F WINAPI D2D1ConvertColorSpace(D2D1_COLOR_SPACE src_colour_space,
863 D2D1_COLOR_SPACE dst_colour_space, const D2D1_COLOR_F *colour)
865 D2D1_COLOR_F ret;
867 TRACE("src_colour_space %#x, dst_colour_space %#x, colour %s.\n",
868 src_colour_space, dst_colour_space, debug_d2d_color_f(colour));
870 if (src_colour_space == D2D1_COLOR_SPACE_CUSTOM || dst_colour_space == D2D1_COLOR_SPACE_CUSTOM)
872 ret.r = 0.0f;
873 ret.g = 0.0f;
874 ret.b = 0.0f;
875 ret.a = 0.0f;
877 return ret;
880 if (src_colour_space == dst_colour_space)
881 return *colour;
883 if (src_colour_space == D2D1_COLOR_SPACE_SRGB && dst_colour_space == D2D1_COLOR_SPACE_SCRGB)
885 ret.r = srgb_inverse_transfer_function(colour->r);
886 ret.g = srgb_inverse_transfer_function(colour->g);
887 ret.b = srgb_inverse_transfer_function(colour->b);
888 ret.a = colour->a;
890 return ret;
893 if (src_colour_space == D2D1_COLOR_SPACE_SCRGB && dst_colour_space == D2D1_COLOR_SPACE_SRGB)
895 ret.r = srgb_transfer_function(colour->r);
896 ret.g = srgb_transfer_function(colour->g);
897 ret.b = srgb_transfer_function(colour->b);
898 ret.a = colour->a;
900 return ret;
903 FIXME("Unhandled conversion from source colour space %#x to destination colour space %#x.\n",
904 src_colour_space, dst_colour_space);
905 ret.r = 0.0f;
906 ret.g = 0.0f;
907 ret.b = 0.0f;
908 ret.a = 0.0f;
910 return ret;
913 static BOOL get_config_key_dword(HKEY default_key, HKEY application_key, const char *name, DWORD *value)
915 DWORD type, data, size;
917 size = sizeof(data);
918 if (application_key && !RegQueryValueExA(application_key,
919 name, 0, &type, (BYTE *)&data, &size) && type == REG_DWORD)
920 goto success;
922 size = sizeof(data);
923 if (default_key && !RegQueryValueExA(default_key,
924 name, 0, &type, (BYTE *)&data, &size) && type == REG_DWORD)
925 goto success;
927 return FALSE;
929 success:
930 *value = data;
931 return TRUE;
934 static void d2d_settings_init(void)
936 HKEY default_key, tmp_key, application_key = NULL;
937 char buffer[MAX_PATH + 10];
938 DWORD len;
940 if (RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Direct2D", &default_key))
941 default_key = NULL;
943 len = GetModuleFileNameA(0, buffer, MAX_PATH);
944 if (len && len < MAX_PATH)
946 char *p, *appname = buffer;
948 if ((p = strrchr(appname, '/')))
949 appname = p + 1;
950 if ((p = strrchr(appname, '\\')))
951 appname = p + 1;
952 strcat(appname, "\\Direct2D");
954 if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmp_key))
956 if (RegOpenKeyA(tmp_key, appname, &application_key))
957 application_key = NULL;
958 RegCloseKey(tmp_key);
962 if (!default_key && !application_key)
963 return;
965 if (get_config_key_dword(default_key, application_key, "max_version_factory", &d2d_settings.max_version_factory))
966 ERR_(winediag)("Limiting maximum Direct2D factory version to %#x.\n", d2d_settings.max_version_factory);
968 if (application_key)
969 RegCloseKey(application_key);
970 if (default_key)
971 RegCloseKey(default_key);
974 BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, void *reserved)
976 if (reason == DLL_PROCESS_ATTACH)
977 d2d_settings_init();
978 return TRUE;