From: Lucian Poston lucian.poston@gmail.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: renamed source file.
dlls/d2d1/Makefile.in | 2 +- dlls/d2d1/d2d1_private.h | 10 ++ dlls/d2d1/{render_target.c => device.c} | 121 ++++++++++++++++++++++++ dlls/d2d1/factory.c | 14 ++- include/d2d1_1.idl | 61 +++++++++++- 5 files changed, 204 insertions(+), 4 deletions(-) rename dlls/d2d1/{render_target.c => device.c} (97%)
diff --git a/dlls/d2d1/Makefile.in b/dlls/d2d1/Makefile.in index 20d3f26f6f..4bfe3b5953 100644 --- a/dlls/d2d1/Makefile.in +++ b/dlls/d2d1/Makefile.in @@ -8,12 +8,12 @@ C_SRCS = \ bitmap_render_target.c \ brush.c \ dc_render_target.c \ + device.c \ factory.c \ geometry.c \ hwnd_render_target.c \ layer.c \ mesh.c \ - render_target.c \ state_block.c \ stroke.c \ wic_render_target.c diff --git a/dlls/d2d1/d2d1_private.h b/dlls/d2d1/d2d1_private.h index dbfb83c249..21e2b8835a 100644 --- a/dlls/d2d1/d2d1_private.h +++ b/dlls/d2d1/d2d1_private.h @@ -477,6 +477,16 @@ void d2d_transformed_geometry_init(struct d2d_geometry *geometry, ID2D1Factory * ID2D1Geometry *src_geometry, const D2D_MATRIX_3X2_F *transform) DECLSPEC_HIDDEN; struct d2d_geometry *unsafe_impl_from_ID2D1Geometry(ID2D1Geometry *iface) DECLSPEC_HIDDEN;
+struct d2d_device +{ + ID2D1Device ID2D1Device_iface; + LONG refcount; + ID2D1Factory1 *factory; + IDXGIDevice *dxgi_device; +}; + +void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *factory, IDXGIDevice *dxgi_device) DECLSPEC_HIDDEN; + static inline BOOL d2d_array_reserve(void **elements, size_t *capacity, size_t count, size_t size) { size_t new_capacity, max_capacity; diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/device.c similarity index 97% rename from dlls/d2d1/render_target.c rename to dlls/d2d1/device.c index 7afbc84ec5..8321b2f6fa 100644 --- a/dlls/d2d1/render_target.c +++ b/dlls/d2d1/device.c @@ -38,6 +38,11 @@ struct d2d_draw_text_layout_ctx D2D1_DRAW_TEXT_OPTIONS options; };
+static inline struct d2d_device *impl_from_ID2D1Device(ID2D1Device *iface) +{ + return CONTAINING_RECORD(iface, struct d2d_device, ID2D1Device_iface); +} + static ID2D1Brush *d2d_draw_get_text_brush(struct d2d_draw_text_layout_ctx *context, IUnknown *effect) { ID2D1Brush *brush = NULL; @@ -3289,3 +3294,119 @@ HRESULT d2d_d3d_render_target_create_rtv(ID2D1RenderTarget *iface, IDXGISurface1
return S_OK; } + +static HRESULT WINAPI d2d_device_QueryInterface(ID2D1Device *iface, REFIID riid, void **out) +{ + TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out); + + if (IsEqualGUID(riid, &IID_ID2D1Device) + || IsEqualGUID(riid, &IID_ID2D1Resource) + || IsEqualGUID(riid, &IID_IUnknown)) + { + ID2D1Device_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d2d_device_AddRef(ID2D1Device *iface) +{ + struct d2d_device *device = impl_from_ID2D1Device(iface); + ULONG refcount = InterlockedIncrement(&device->refcount); + + TRACE("%p increasing refcount to %u.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI d2d_device_Release(ID2D1Device *iface) +{ + struct d2d_device *device = impl_from_ID2D1Device(iface); + ULONG refcount = InterlockedDecrement(&device->refcount); + + TRACE("%p decreasing refcount to %u.\n", iface, refcount); + + if (refcount == 0) + { + IDXGIDevice_Release(device->dxgi_device); + ID2D1Factory1_Release(device->factory); + heap_free(device); + } + + return refcount; +} + +static void WINAPI d2d_device_GetFactory(ID2D1Device *iface, ID2D1Factory **factory) +{ + struct d2d_device *device = impl_from_ID2D1Device(iface); + + TRACE("iface %p, factory %p.\n", iface, factory); + + *factory = (ID2D1Factory *)device->factory; + ID2D1Factory1_AddRef(device->factory); +} + +static HRESULT WINAPI d2d_device_CreateDeviceContext(ID2D1Device *iface, D2D1_DEVICE_CONTEXT_OPTIONS options, + ID2D1DeviceContext **context) +{ + FIXME("iface %p, options %#x, context %p stub!\n", iface, options, context); + + return E_NOTIMPL; +} + +static HRESULT WINAPI d2d_device_CreatePrintControl(ID2D1Device *iface, IWICImagingFactory *wic_factory, + IPrintDocumentPackageTarget *document_target, const D2D1_PRINT_CONTROL_PROPERTIES *desc, + ID2D1PrintControl **print_control) +{ + FIXME("iface %p, wic_factory %p, document_target %p, desc %p, print_control %p stub!\n", iface, wic_factory, + document_target, desc, print_control); + + return E_NOTIMPL; +} + +static void WINAPI d2d_device_SetMaximumTextureMemory(ID2D1Device *iface, UINT64 max_texture_memory) +{ + FIXME("iface %p, max_texture_memory %s stub!\n", iface, wine_dbgstr_longlong(max_texture_memory)); +} + +static UINT64 WINAPI d2d_device_GetMaximumTextureMemory(ID2D1Device *iface) +{ + FIXME("iface %p stub!\n", iface); + + return 0; +} + +static HRESULT WINAPI d2d_device_ClearResources(ID2D1Device *iface, UINT msec_since_use) +{ + FIXME("iface %p, msec_since_use %u stub!\n", iface, msec_since_use); + + return E_NOTIMPL; +} + +static const struct ID2D1DeviceVtbl d2d_device_vtbl = +{ + d2d_device_QueryInterface, + d2d_device_AddRef, + d2d_device_Release, + d2d_device_GetFactory, + d2d_device_CreateDeviceContext, + d2d_device_CreatePrintControl, + d2d_device_SetMaximumTextureMemory, + d2d_device_GetMaximumTextureMemory, + d2d_device_ClearResources, +}; + +void d2d_device_init(struct d2d_device *device, ID2D1Factory1 *iface, IDXGIDevice *dxgi_device) +{ + device->ID2D1Device_iface.lpVtbl = &d2d_device_vtbl; + device->refcount = 1; + device->factory = iface; + ID2D1Factory1_AddRef(device->factory); + device->dxgi_device = dxgi_device; + IDXGIDevice_AddRef(device->dxgi_device); +} diff --git a/dlls/d2d1/factory.c b/dlls/d2d1/factory.c index 9bacc8583c..7810e957d4 100644 --- a/dlls/d2d1/factory.c +++ b/dlls/d2d1/factory.c @@ -375,9 +375,19 @@ static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDCRenderTarget(ID2D1Factory1 static HRESULT STDMETHODCALLTYPE d2d_factory_CreateDevice(ID2D1Factory1 *iface, IDXGIDevice *dxgi_device, ID2D1Device **device) { - FIXME("iface %p, dxgi_device %p, device %p stub!\n", iface, dxgi_device, device); + struct d2d_device *object;
- return E_NOTIMPL; + TRACE("iface %p, dxgi_device %p, device %p.\n", iface, dxgi_device, device); + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + d2d_device_init(object, iface, dxgi_device); + + TRACE("Create device %p.\n", object); + *device = &object->ID2D1Device_iface; + + return S_OK; }
static HRESULT STDMETHODCALLTYPE d2d_factory_CreateStrokeStyle1(ID2D1Factory1 *iface, diff --git a/include/d2d1_1.idl b/include/d2d1_1.idl index 1fbbb301dd..8f8b40b1d9 100644 --- a/include/d2d1_1.idl +++ b/include/d2d1_1.idl @@ -18,12 +18,22 @@
import "d2d1.idl";
-interface ID2D1Device; +interface ID2D1DeviceContext; interface ID2D1StrokeStyle1; interface ID2D1PathGeometry1; interface ID2D1DrawingStateBlock1; interface ID2D1GdiMetafile; interface ID2D1Properties; +interface IPrintDocumentPackageTarget; +interface ID2D1PrintControl; +interface IWICImagingFactory; + +typedef enum D2D1_DEVICE_CONTEXT_OPTIONS +{ + D2D1_DEVICE_CONTEXT_OPTIONS_NONE = 0, + D2D1_DEVICE_CONTEXT_OPTIONS_ENABLE_MULTITHREADED_OPTIMIZATIONS = 1, + D2D1_DEVICE_CONTEXT_OPTIONS_FORCE_DWORD = 0xffffffff, +} D2D1_DEVICE_CONTEXT_OPTIONS;
typedef enum D2D1_STROKE_TRANSFORM_TYPE { @@ -77,6 +87,55 @@ typedef struct D2D1_DRAWING_STATE_DESCRIPTION1
typedef HRESULT (__stdcall *PD2D1_EFFECT_FACTORY)(IUnknown **effect);
+typedef enum D2D1_PRINT_FONT_SUBSET_MODE +{ + D2D1_PRINT_FONT_SUBSET_MODE_DEFAULT = 0, + D2D1_PRINT_FONT_SUBSET_MODE_EACHPAGE = 1, + D2D1_PRINT_FONT_SUBSET_MODE_NONE = 2, + D2D1_PRINT_FONT_SUBSET_MODE_FORCE_DWORD = 0xffffffff, +} D2D1_PRINT_FONT_SUBSET_MODE; + +typedef enum D2D1_COLOR_SPACE +{ + D2D1_COLOR_SPACE_CUSTOM = 0, + D2D1_COLOR_SPACE_SRGB = 1, + D2D1_COLOR_SPACE_SCRGB = 2, + D2D1_COLOR_SPACE_FORCE_DWORD = 0xffffffff, +} D2D1_COLOR_SPACE; + +typedef struct D2D1_PRINT_CONTROL_PROPERTIES +{ + D2D1_PRINT_FONT_SUBSET_MODE fontSubset; + FLOAT rasterDPI; + D2D1_COLOR_SPACE colorSpace; +} D2D1_PRINT_CONTROL_PROPERTIES; + +[ + object, + uuid(47dd575d-ac05-4cdd-8049-9b02cd16f44c), + local, +] +interface ID2D1Device : ID2D1Resource +{ + HRESULT CreateDeviceContext( + [in] D2D1_DEVICE_CONTEXT_OPTIONS options, + [out] ID2D1DeviceContext **context + ); + HRESULT CreatePrintControl( + [in] IWICImagingFactory *wic_factory, + [in] IPrintDocumentPackageTarget *document_target, + [in] const D2D1_PRINT_CONTROL_PROPERTIES *desc, + [out] ID2D1PrintControl **print_control + ); + void SetMaximumTextureMemory( + [in] UINT64 max_texture_memory + ); + UINT64 GetMaximumTextureMemory(); + HRESULT ClearResources( + [in, defaultvalue(0)] UINT msec_since_use + ); +} + [ object, uuid(bb12d362-daee-4b9a-aa1d-14ba401cfa1f),
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d2d1/tests/d2d1.c | 45 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c index 9bd9e2b19d..1bb1a38c9c 100644 --- a/dlls/d2d1/tests/d2d1.c +++ b/dlls/d2d1/tests/d2d1.c @@ -19,7 +19,7 @@ #define COBJMACROS #include <limits.h> #include <math.h> -#include "d2d1.h" +#include "d2d1_1.h" #include "wincrypt.h" #include "wine/test.h" #include "initguid.h" @@ -6426,6 +6426,48 @@ static void test_bezier_intersect(void) DestroyWindow(window); }
+static void test_create_device(void) +{ + ID3D10Device1 *d3d_device; + IDXGIDevice *dxgi_device; + ID2D1Factory1 *factory; + ID2D1Factory *factory2; + ID2D1Device *device; + ULONG refcount; + HRESULT hr; + + if (!(d3d_device = create_device())) + { + skip("Failed to create device, skipping tests.\n"); + return; + } + + hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory); + if (FAILED(hr)) + { + win_skip("ID2D1Factory1 is not supported.\n"); + ID3D10Device1_Release(d3d_device); + return; + } + + hr = ID3D10Device1_QueryInterface(d3d_device, &IID_IDXGIDevice, (void **)&dxgi_device); + ok(SUCCEEDED(hr), "Failed to get IDXGIDevice interface.\n"); + + hr = ID2D1Factory1_CreateDevice(factory, dxgi_device, &device); + ok(SUCCEEDED(hr), "Failed to get ID2D1Device, hr %#x.\n", hr); + + ID2D1Device_GetFactory(device, &factory2); + ok(factory2 == (ID2D1Factory *)factory, "Unexpected factory pointer.\n"); + ID2D1Factory_Release(factory2); + ID2D1Device_Release(device); + + IDXGIDevice_Release(dxgi_device); + ID3D10Device1_Release(d3d_device); + + refcount = ID2D1Factory1_Release(factory); + ok(!refcount, "Factory has %u references left.\n", refcount); +} + START_TEST(d2d1) { test_clip(); @@ -6454,4 +6496,5 @@ START_TEST(d2d1) test_gdi_interop(); test_layer(); test_bezier_intersect(); + test_create_device(); }