From: Jaakko Hannikainen <jgke@jgke.fi> These stub implementations enable Dorico to successfully boot. They don't implement any real rendering or linkings to rendering contexts, they just create various interfaces with methods returning E_NOTIMPL. --- configure | 1 + configure.ac | 1 + dlls/dcomp/Makefile.in | 10 +- dlls/dcomp/composition_desktop_device.c | 322 +++++++++++++++++++++++ dlls/dcomp/composition_device.c | 330 ++++++++++++++++++++++++ dlls/dcomp/dcomp_private.h | 73 ++++++ dlls/dcomp/{device.c => main.c} | 29 ++- dlls/dcomp/surface.c | 183 +++++++++++++ dlls/dcomp/surface_factory.c | 136 ++++++++++ dlls/dcomp/target.c | 129 +++++++++ dlls/dcomp/tests/Makefile.in | 5 + dlls/dcomp/tests/dcomp.c | 166 ++++++++++++ dlls/dcomp/visual2.c | 277 ++++++++++++++++++++ 13 files changed, 1657 insertions(+), 5 deletions(-) create mode 100644 dlls/dcomp/composition_desktop_device.c create mode 100644 dlls/dcomp/composition_device.c create mode 100644 dlls/dcomp/dcomp_private.h rename dlls/dcomp/{device.c => main.c} (62%) create mode 100644 dlls/dcomp/surface.c create mode 100644 dlls/dcomp/surface_factory.c create mode 100644 dlls/dcomp/target.c create mode 100644 dlls/dcomp/tests/Makefile.in create mode 100644 dlls/dcomp/tests/dcomp.c create mode 100644 dlls/dcomp/visual2.c diff --git a/configure b/configure index 667b8f215bc..1fff3fc42f3 100755 --- a/configure +++ b/configure @@ -22508,6 +22508,7 @@ wine_fn_config_makefile dlls/dbghelp enable_dbghelp wine_fn_config_makefile dlls/dbghelp/tests enable_tests wine_fn_config_makefile dlls/dciman32 enable_dciman32 wine_fn_config_makefile dlls/dcomp enable_dcomp +wine_fn_config_makefile dlls/dcomp/tests enable_tests wine_fn_config_makefile dlls/ddeml.dll16 enable_win16 wine_fn_config_makefile dlls/ddraw enable_ddraw wine_fn_config_makefile dlls/ddraw/tests enable_tests diff --git a/configure.ac b/configure.ac index 1d3165dff84..1e10930dfa8 100644 --- a/configure.ac +++ b/configure.ac @@ -2650,6 +2650,7 @@ WINE_CONFIG_MAKEFILE(dlls/dbghelp) WINE_CONFIG_MAKEFILE(dlls/dbghelp/tests) WINE_CONFIG_MAKEFILE(dlls/dciman32) WINE_CONFIG_MAKEFILE(dlls/dcomp) +WINE_CONFIG_MAKEFILE(dlls/dcomp/tests) WINE_CONFIG_MAKEFILE(dlls/ddeml.dll16) WINE_CONFIG_MAKEFILE(dlls/ddraw) WINE_CONFIG_MAKEFILE(dlls/ddraw/tests) diff --git a/dlls/dcomp/Makefile.in b/dlls/dcomp/Makefile.in index d48b901a4fb..1664d40aec9 100644 --- a/dlls/dcomp/Makefile.in +++ b/dlls/dcomp/Makefile.in @@ -1,7 +1,15 @@ MODULE = dcomp.dll EXTRADLLFLAGS = -Wb,--prefer-native +IMPORTLIB = dcomp +IMPORTS = dxgi uuid ole32 user32 SOURCES = \ - device.c \ + main.c \ + composition_device.c \ + composition_desktop_device.c \ + surface_factory.c \ + surface.c \ + target.c \ + visual2.c \ version.rc diff --git a/dlls/dcomp/composition_desktop_device.c b/dlls/dcomp/composition_desktop_device.c new file mode 100644 index 00000000000..7cd5a159d68 --- /dev/null +++ b/dlls/dcomp/composition_desktop_device.c @@ -0,0 +1,322 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_desktop_device *impl_from_IDCompositionDesktopDevice(IDCompositionDesktopDevice *iface) +{ + return CONTAINING_RECORD(iface, struct composition_desktop_device, IDCompositionDesktopDevice_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_desktop_device_QueryInterface( + IDCompositionDesktopDevice *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionDesktopDevice)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_desktop_device_AddRef(IDCompositionDesktopDevice *iface) +{ + struct composition_desktop_device *factory = impl_from_IDCompositionDesktopDevice(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_desktop_device_Release(IDCompositionDesktopDevice *iface) +{ + struct composition_desktop_device *device = impl_from_IDCompositionDesktopDevice(iface); + ULONG refcount = InterlockedDecrement(&device->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(device); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_Commit(IDCompositionDesktopDevice *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_WaitForCommitCompletion(IDCompositionDesktopDevice *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_GetFrameStatistics( + IDCompositionDesktopDevice *iface, DCOMPOSITION_FRAME_STATISTICS *statistics) +{ + FIXME("iface %p statistics %p stub!\n", iface, statistics); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateVisual( + IDCompositionDesktopDevice *iface, IDCompositionVisual2 **visual) +{ + return create_composition_visual(visual); +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateSurfaceFactory( + IDCompositionDesktopDevice *iface, + IUnknown *rendering_device, + IDCompositionSurfaceFactory **surface_factory) +{ + return create_composition_surface_factory(surface_factory); +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateSurface( + IDCompositionDesktopDevice *iface, UINT width, UINT height, + DXGI_FORMAT pixel_format, DXGI_ALPHA_MODE alpha_mode, IDCompositionSurface **surface) +{ + FIXME("iface %p width %u height %u pixel_format %#x alpha_mode %#x surface %p stub!\n", + iface, width, height, pixel_format, alpha_mode, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateVirtualSurface( + IDCompositionDesktopDevice *iface, UINT width, UINT height, + DXGI_FORMAT pixel_format, DXGI_ALPHA_MODE alpha_mode, IDCompositionVirtualSurface **surface) +{ + FIXME("iface %p width %u height %u pixel_format %#x alpha_mode %#x surface %p stub!\n", + iface, width, height, pixel_format, alpha_mode, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateTranslateTransform( + IDCompositionDesktopDevice *iface, IDCompositionTranslateTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateScaleTransform( + IDCompositionDesktopDevice *iface, IDCompositionScaleTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateRotateTransform( + IDCompositionDesktopDevice *iface, IDCompositionRotateTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateSkewTransform( + IDCompositionDesktopDevice *iface, IDCompositionSkewTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateMatrixTransform( + IDCompositionDesktopDevice *iface, IDCompositionMatrixTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateTransformGroup( + IDCompositionDesktopDevice *iface, IDCompositionTransform **transforms, + UINT elements, IDCompositionTransform **transform_group) +{ + FIXME("iface %p transforms %p elemens %u transform_group %p stub!\n", + iface, transforms, elements, transform_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateTranslateTransform3D( + IDCompositionDesktopDevice *iface, IDCompositionTranslateTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateScaleTransform3D( + IDCompositionDesktopDevice *iface, IDCompositionScaleTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateRotateTransform3D( + IDCompositionDesktopDevice *iface, IDCompositionRotateTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateMatrixTransform3D( + IDCompositionDesktopDevice *iface, IDCompositionMatrixTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateTransform3DGroup( + IDCompositionDesktopDevice *iface, IDCompositionTransform3D **transforms_3d, + UINT elements, IDCompositionTransform3D **transform_3d_group) +{ + FIXME("iface %p transforms_3d %p elements %u transform_3d_group %p stub!\n", + iface, transforms_3d, elements, transform_3d_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateEffectGroup( + IDCompositionDesktopDevice *iface, IDCompositionEffectGroup **effect_group) +{ + FIXME("iface %p effect_group %p stub!\n", iface, effect_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateRectangleClip( + IDCompositionDesktopDevice *iface, IDCompositionRectangleClip **clip) +{ + FIXME("iface %p clip %p stub!\n", iface, clip); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateAnimation( + IDCompositionDesktopDevice *iface, IDCompositionAnimation **animation) +{ + FIXME("iface %p animation %p stub!\n", iface, animation); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateTargetForHwnd( + IDCompositionDesktopDevice *iface, HWND hwnd, BOOL topmost, IDCompositionTarget **target) +{ + return create_composition_target(hwnd, topmost, target); +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateSurfaceFromHandle( + IDCompositionDesktopDevice *iface, HANDLE handle, IUnknown **surface) +{ + FIXME("iface %p handle %p surface %p stub!\n", iface, handle, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_CreateSurfaceFromHwnd( + IDCompositionDesktopDevice *iface, HWND hwnd, IUnknown **surface) +{ + FIXME("iface %p hwnd %p surface %p stub!\n", iface, hwnd, surface); + return E_NOTIMPL; +} + +static const struct IDCompositionDesktopDeviceVtbl composition_desktop_device_vtbl = +{ + composition_desktop_device_QueryInterface, + composition_desktop_device_AddRef, + composition_desktop_device_Release, + + /* IDCompositionDevice2 methods */ + composition_desktop_device_Commit, + composition_desktop_device_WaitForCommitCompletion, + composition_desktop_device_GetFrameStatistics, + composition_desktop_device_CreateVisual, + composition_desktop_device_CreateSurfaceFactory, + composition_desktop_device_CreateSurface, + composition_desktop_device_CreateVirtualSurface, + composition_desktop_device_CreateTranslateTransform, + composition_desktop_device_CreateScaleTransform, + composition_desktop_device_CreateRotateTransform, + composition_desktop_device_CreateSkewTransform, + composition_desktop_device_CreateMatrixTransform, + composition_desktop_device_CreateTransformGroup, + composition_desktop_device_CreateTranslateTransform3D, + composition_desktop_device_CreateScaleTransform3D, + composition_desktop_device_CreateRotateTransform3D, + composition_desktop_device_CreateMatrixTransform3D, + composition_desktop_device_CreateTransform3DGroup, + composition_desktop_device_CreateEffectGroup, + composition_desktop_device_CreateRectangleClip, + composition_desktop_device_CreateAnimation, + + /* IDCompositionDesktopDevice methods */ + composition_desktop_device_CreateTargetForHwnd, + composition_desktop_device_CreateSurfaceFromHandle, + composition_desktop_device_CreateSurfaceFromHwnd, +}; + +static HRESULT STDMETHODCALLTYPE composition_desktop_device_init( + IUnknown *rendering_device, struct composition_desktop_device *device) +{ + device->IDCompositionDesktopDevice_iface.lpVtbl = &composition_desktop_device_vtbl; + device->refcount = 1; + return S_OK; +} + +HRESULT create_composition_desktop_device(IUnknown *rendering_device, void **device) +{ + struct composition_desktop_device *composition_device; + HRESULT hr; + + if(!(composition_device = calloc(1, sizeof(*composition_device)))) + { + ERR("Failed to allocate composition_device memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_desktop_device_init(rendering_device, composition_device); + if (FAILED(hr)) + { + WARN("Failed to initialize composition_device, hr %#lx.\n", hr); + free(composition_device); + *device = NULL; + return hr; + } + + TRACE("Created composition_device %p.\n", composition_device); + *device = &composition_device->IDCompositionDesktopDevice_iface; + + return S_OK; +} diff --git a/dlls/dcomp/composition_device.c b/dlls/dcomp/composition_device.c new file mode 100644 index 00000000000..0087bba5608 --- /dev/null +++ b/dlls/dcomp/composition_device.c @@ -0,0 +1,330 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_device *impl_from_IDCompositionDevice(IDCompositionDevice *iface) +{ + return CONTAINING_RECORD(iface, struct composition_device, IDCompositionDevice_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_device_QueryInterface( + IDCompositionDevice *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionDevice)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_device_AddRef(IDCompositionDevice *iface) +{ + struct composition_device *factory = impl_from_IDCompositionDevice(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_device_Release(IDCompositionDevice *iface) +{ + struct composition_device *composition_device = impl_from_IDCompositionDevice(iface); + ULONG refcount = InterlockedDecrement(&composition_device->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(composition_device); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE composition_device_Commit(IDCompositionDevice *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_WaitForCommitCompletion(IDCompositionDevice *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_GetFrameStatistics( + IDCompositionDevice *iface, DCOMPOSITION_FRAME_STATISTICS *statistics) +{ + FIXME("iface %p statistics %p stub!\n", iface, statistics); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateTargetForHwnd( + IDCompositionDevice *iface, HWND hwnd, BOOL topmost, IDCompositionTarget **target) +{ + return create_composition_target(hwnd, topmost, target); +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateVisual( + IDCompositionDevice *iface, IDCompositionVisual **visual) +{ + FIXME("iface %p visual %p stub!\n", iface, visual); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateSurface( + IDCompositionDevice *iface, + UINT width, + UINT height, + DXGI_FORMAT pixel_format, + DXGI_ALPHA_MODE alpha_mode, + IDCompositionSurface **surface) +{ + FIXME("iface %p width %u height %u pixel_format %#x alpha_mode %#x surface %p stub!\n", + iface, width, height, pixel_format, alpha_mode, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateVirtualSurface( + IDCompositionDevice *iface, + UINT width, + UINT height, + DXGI_FORMAT pixel_format, + DXGI_ALPHA_MODE alpha_mode, + IDCompositionVirtualSurface **surface) +{ + FIXME("iface %p width %u height %u pixel_format %#x alpha_mode %#x surface %p stub!\n", + iface, width, height, pixel_format, alpha_mode, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateSurfaceFromHandle( + IDCompositionDevice *iface, HANDLE handle, IUnknown **surface) +{ + FIXME("iface %p handle %p surface %p stub!\n", iface, handle, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateSurfaceFromHwnd( + IDCompositionDevice *iface, HWND hwnd, IUnknown **surface) +{ + FIXME("iface %p hwnd %p surface %p stub!\n", iface, hwnd, surface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateTranslateTransform( + IDCompositionDevice *iface, IDCompositionTranslateTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateScaleTransform( + IDCompositionDevice *iface, IDCompositionScaleTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateRotateTransform( + IDCompositionDevice *iface, IDCompositionRotateTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateSkewTransform( + IDCompositionDevice *iface, IDCompositionSkewTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateMatrixTransform( + IDCompositionDevice *iface, IDCompositionMatrixTransform **transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateTransformGroup( + IDCompositionDevice *iface, + IDCompositionTransform **transforms, + UINT elements, + IDCompositionTransform **transform_group) +{ + FIXME("iface %p transforms %p elements %u transform_group %p stub!\n", + iface, transforms, elements, transform_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateTranslateTransform3D( + IDCompositionDevice *iface, IDCompositionTranslateTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateScaleTransform3D( + IDCompositionDevice *iface, IDCompositionScaleTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateRotateTransform3D( + IDCompositionDevice *iface, IDCompositionRotateTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateMatrixTransform3D( + IDCompositionDevice *iface, IDCompositionMatrixTransform3D **transform_3d) +{ + FIXME("iface %p transform_3d %p stub!\n", iface, transform_3d); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateTransform3DGroup( + IDCompositionDevice *iface, + IDCompositionTransform3D **transforms_3d, + UINT elements, + IDCompositionTransform3D **transform_3d_group) +{ + FIXME("iface %p transforms_3d %p elements %u transform_3d_group %p stub!\n", + iface, transforms_3d, elements, transform_3d_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateEffectGroup( + IDCompositionDevice *iface, IDCompositionEffectGroup **effect_group) +{ + FIXME("iface %p effect_group %p stub!\n", iface, effect_group); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateRectangleClip( + IDCompositionDevice *iface, IDCompositionRectangleClip **clip) +{ + FIXME("iface %p clip %p stub!\n", iface, clip); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CreateAnimation( + IDCompositionDevice *iface, IDCompositionAnimation **animation) +{ + FIXME("iface %p animation %p stub!\n", iface, animation); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_device_CheckDeviceState( + IDCompositionDevice *iface, BOOL *valid) +{ + FIXME("iface %p valid %p stub!\n", iface, valid); + return E_NOTIMPL; +} + +static const struct IDCompositionDeviceVtbl composition_device_vtbl = +{ + composition_device_QueryInterface, + composition_device_AddRef, + composition_device_Release, + composition_device_Commit, + composition_device_WaitForCommitCompletion, + composition_device_GetFrameStatistics, + composition_device_CreateTargetForHwnd, + composition_device_CreateVisual, + composition_device_CreateSurface, + composition_device_CreateVirtualSurface, + composition_device_CreateSurfaceFromHandle, + composition_device_CreateSurfaceFromHwnd, + composition_device_CreateTranslateTransform, + composition_device_CreateScaleTransform, + composition_device_CreateRotateTransform, + composition_device_CreateSkewTransform, + composition_device_CreateMatrixTransform, + composition_device_CreateTransformGroup, + composition_device_CreateTranslateTransform3D, + composition_device_CreateScaleTransform3D, + composition_device_CreateRotateTransform3D, + composition_device_CreateMatrixTransform3D, + composition_device_CreateTransform3DGroup, + composition_device_CreateEffectGroup, + composition_device_CreateRectangleClip, + composition_device_CreateAnimation, + composition_device_CheckDeviceState, +}; + +static HRESULT STDMETHODCALLTYPE composition_device_init( + IDXGIDevice *dxgi_device, struct composition_device *composition_device) +{ + composition_device->IDCompositionDevice_iface.lpVtbl = &composition_device_vtbl; + composition_device->refcount = 1; + return S_OK; +} + +HRESULT create_composition_device(IDXGIDevice *dxgi_device, void **device) +{ + struct composition_device *composition_device; + HRESULT hr; + + if(!(composition_device = calloc(1, sizeof(*composition_device)))) + { + ERR("Failed to allocate device memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_device_init(dxgi_device, composition_device); + if (FAILED(hr)) + { + WARN("Failed to initialize device, hr %#lx.\n", hr); + free(composition_device); + *device = NULL; + return hr; + } + + TRACE("Created device %p.\n", composition_device); + *device = &composition_device->IDCompositionDevice_iface; + + return S_OK; +} diff --git a/dlls/dcomp/dcomp_private.h b/dlls/dcomp/dcomp_private.h new file mode 100644 index 00000000000..330a8ce2468 --- /dev/null +++ b/dlls/dcomp/dcomp_private.h @@ -0,0 +1,73 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_DCOMP_PRIVATE_H +#define __WINE_DCOMP_PRIVATE_H + +#include "dcomp.h" + +/* IDCompositionDevice */ +struct composition_device +{ + IDCompositionDevice IDCompositionDevice_iface; + LONG refcount; +}; + +/* IDCompositionDesktopDevice */ +struct composition_desktop_device +{ + IDCompositionDesktopDevice IDCompositionDesktopDevice_iface; + LONG refcount; +}; + +/* IDCompositionTarget */ +struct composition_target +{ + IDCompositionTarget IDCompositionTarget_iface; + LONG refcount; +}; + +/* IDCompositionVisual */ +struct composition_visual +{ + IDCompositionVisual2 IDCompositionVisual2_iface; + LONG refcount; +}; + +/* IDCompositionSurfaceFactory */ +struct composition_surface_factory +{ + IDCompositionSurfaceFactory IDCompositionSurfaceFactory_iface; + LONG refcount; +}; + +/* IDCompositionVirtualSurface */ +struct composition_virtual_surface +{ + IDCompositionVirtualSurface IDCompositionVirtualSurface_iface; + LONG refcount; +}; + +HRESULT create_composition_device(IDXGIDevice *dxgi_device, void **device); +HRESULT create_composition_desktop_device(IUnknown *rendering_device, void **device); +HRESULT create_composition_target(HWND hwnd, BOOL topmost, IDCompositionTarget **target); +HRESULT create_composition_visual(IDCompositionVisual2 **visual); +HRESULT create_composition_surface_factory(IDCompositionSurfaceFactory **surface_factory); +HRESULT create_composition_virtual_surface(IDCompositionVirtualSurface **virtual_surface); + +#endif /* __WINE_DCOMP_PRIVATE_H */ diff --git a/dlls/dcomp/device.c b/dlls/dcomp/main.c similarity index 62% rename from dlls/dcomp/device.c rename to dlls/dcomp/main.c index 2744d758e91..780b20d37f0 100644 --- a/dlls/dcomp/device.c +++ b/dlls/dcomp/main.c @@ -1,5 +1,6 @@ /* * Copyright 2020 Nikolay Sivov for CodeWeavers + * Copyright 2025 Jaakko Hannikainen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,21 +23,41 @@ #include "objidl.h" #include "dxgi.h" #include "wine/debug.h" +#include "initguid.h" +#include "dcomp.h" +#include "dcomp_private.h" WINE_DEFAULT_DEBUG_CHANNEL(dcomp); HRESULT WINAPI DCompositionCreateDevice(IDXGIDevice *dxgi_device, REFIID iid, void **device) { - FIXME("%p, %s, %p.\n", dxgi_device, debugstr_guid(iid), device); + if(IsEqualGUID(iid, &IID_IDCompositionDevice)) + { + return create_composition_device(dxgi_device, device); + } - return E_NOTIMPL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *device = NULL; + + return E_NOINTERFACE; } HRESULT WINAPI DCompositionCreateDevice2(IUnknown *rendering_device, REFIID iid, void **device) { - FIXME("%p, %s, %p.\n", rendering_device, debugstr_guid(iid), device); + if(IsEqualGUID(iid, &IID_IDCompositionDevice)) + { + FIXME("%p, %s, %p.\n", rendering_device, debugstr_guid(iid), device); + return E_NOTIMPL; + } + if(IsEqualGUID(iid, &IID_IDCompositionDesktopDevice)) + { + return create_composition_desktop_device(rendering_device, device); + } - return E_NOTIMPL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *device = NULL; + + return E_NOINTERFACE; } HRESULT WINAPI DCompositionCreateDevice3(IUnknown *rendering_device, REFIID iid, void **device) diff --git a/dlls/dcomp/surface.c b/dlls/dcomp/surface.c new file mode 100644 index 00000000000..38648a9f920 --- /dev/null +++ b/dlls/dcomp/surface.c @@ -0,0 +1,183 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_virtual_surface *impl_from_IDCompositionVirtualSurface(IDCompositionVirtualSurface *iface) +{ + return CONTAINING_RECORD(iface, struct composition_virtual_surface, IDCompositionVirtualSurface_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_virtual_surface_QueryInterface( + IDCompositionVirtualSurface *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionVisual)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_virtual_surface_AddRef(IDCompositionVirtualSurface *iface) +{ + struct composition_virtual_surface *factory = impl_from_IDCompositionVirtualSurface(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_virtual_surface_Release(IDCompositionVirtualSurface *iface) +{ + struct composition_virtual_surface *composition_virtual_surface = impl_from_IDCompositionVirtualSurface(iface); + ULONG refcount = InterlockedDecrement(&composition_virtual_surface->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(composition_virtual_surface); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_BeginDraw( + IDCompositionVirtualSurface *iface, const RECT *rect, + REFIID iid, void **object, POINT *offset) +{ + FIXME("iface %p rect %p iid %s object %p offset %p stub!\n", + iface, rect, debugstr_guid(iid), object, offset); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_EndDraw(IDCompositionVirtualSurface *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_SuspendDraw(IDCompositionVirtualSurface *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_ResumeDraw(IDCompositionVirtualSurface *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_Scroll( + IDCompositionVirtualSurface *iface, const RECT *scroll, const RECT *clip, + int offset_x, int offset_y) +{ + FIXME("iface %p scroll %p clip %p offset_x %d offset_y %d stub!\n", + iface, scroll, clip, offset_x, offset_y); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_Resize( + IDCompositionVirtualSurface *iface, UINT width, UINT height) +{ + FIXME("iface %p width %u height %u stub!\n", iface, width, height); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_Trim( + IDCompositionVirtualSurface *iface, const RECT *rectangles, UINT count) +{ + FIXME("iface %p rectangles %p count %u stub!\n", iface, rectangles, count); + return E_NOTIMPL; +} + + +static const struct IDCompositionVirtualSurfaceVtbl composition_virtual_surface_vtbl = +{ + composition_virtual_surface_QueryInterface, + composition_virtual_surface_AddRef, + composition_virtual_surface_Release, + + /* IDCompositionSurface methods */ + composition_virtual_surface_BeginDraw, + composition_virtual_surface_EndDraw, + composition_virtual_surface_SuspendDraw, + composition_virtual_surface_ResumeDraw, + composition_virtual_surface_Scroll, + + /* IDCompositionVirtualSurface methods */ + composition_virtual_surface_Resize, + composition_virtual_surface_Trim, +}; + +static HRESULT STDMETHODCALLTYPE composition_virtual_surface_init( + struct composition_virtual_surface *composition_virtual_surface) +{ + composition_virtual_surface->IDCompositionVirtualSurface_iface.lpVtbl = &composition_virtual_surface_vtbl; + composition_virtual_surface->refcount = 1; + return S_OK; +} + +HRESULT create_composition_virtual_surface(IDCompositionVirtualSurface **virtual_surface) +{ + struct composition_virtual_surface *composition_virtual_surface; + HRESULT hr; + + if(!(composition_virtual_surface = calloc(1, sizeof(*composition_virtual_surface)))) + { + ERR("Failed to allocate composition virtual_surface memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_virtual_surface_init(composition_virtual_surface); + if (FAILED(hr)) + { + WARN("Failed to initialize composition virtual_surface, hr %#lx.\n", hr); + free(composition_virtual_surface); + *virtual_surface = NULL; + return hr; + } + + TRACE("Created composition virtual_surface %p.\n", composition_virtual_surface); + *virtual_surface = &composition_virtual_surface->IDCompositionVirtualSurface_iface; + + return S_OK; +} diff --git a/dlls/dcomp/surface_factory.c b/dlls/dcomp/surface_factory.c new file mode 100644 index 00000000000..273c8801f3b --- /dev/null +++ b/dlls/dcomp/surface_factory.c @@ -0,0 +1,136 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_surface_factory *impl_from_IDCompositionSurfaceFactory(IDCompositionSurfaceFactory *iface) +{ + return CONTAINING_RECORD(iface, struct composition_surface_factory, IDCompositionSurfaceFactory_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_surface_factory_QueryInterface( + IDCompositionSurfaceFactory *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionVisual)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_surface_factory_AddRef(IDCompositionSurfaceFactory *iface) +{ + struct composition_surface_factory *factory = impl_from_IDCompositionSurfaceFactory(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_surface_factory_Release(IDCompositionSurfaceFactory *iface) +{ + struct composition_surface_factory *composition_surface_factory = impl_from_IDCompositionSurfaceFactory(iface); + ULONG refcount = InterlockedDecrement(&composition_surface_factory->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(composition_surface_factory); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE composition_surface_factory_CreateSurface( + IDCompositionSurfaceFactory *iface, UINT width, UINT height, + DXGI_FORMAT pixel_format, DXGI_ALPHA_MODE alpha_mode, IDCompositionSurface **surface) +{ + return create_composition_virtual_surface((IDCompositionVirtualSurface **)surface); +} +static HRESULT STDMETHODCALLTYPE composition_surface_factory_CreateVirtualSurface( + IDCompositionSurfaceFactory *iface, UINT width, UINT height, + DXGI_FORMAT pixel_format, DXGI_ALPHA_MODE alpha_mode, IDCompositionVirtualSurface **surface) +{ + return create_composition_virtual_surface(surface); +} + +static const struct IDCompositionSurfaceFactoryVtbl composition_surface_factory_vtbl = +{ + composition_surface_factory_QueryInterface, + composition_surface_factory_AddRef, + composition_surface_factory_Release, + composition_surface_factory_CreateSurface, + composition_surface_factory_CreateVirtualSurface, +}; + +static HRESULT STDMETHODCALLTYPE composition_surface_factory_init( + struct composition_surface_factory *composition_surface_factory) +{ + composition_surface_factory->IDCompositionSurfaceFactory_iface.lpVtbl = &composition_surface_factory_vtbl; + composition_surface_factory->refcount = 1; + return S_OK; +} + +HRESULT create_composition_surface_factory(IDCompositionSurfaceFactory **surface_factory) +{ + struct composition_surface_factory *composition_surface_factory; + HRESULT hr; + + if(!(composition_surface_factory = calloc(1, sizeof(*composition_surface_factory)))) + { + ERR("Failed to allocate composition surface_factory memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_surface_factory_init(composition_surface_factory); + if (FAILED(hr)) + { + WARN("Failed to initialize composition surface_factory, hr %#lx.\n", hr); + free(composition_surface_factory); + *surface_factory = NULL; + return hr; + } + + TRACE("Created composition surface_factory %p.\n", composition_surface_factory); + *surface_factory = &composition_surface_factory->IDCompositionSurfaceFactory_iface; + + return S_OK; +} diff --git a/dlls/dcomp/target.c b/dlls/dcomp/target.c new file mode 100644 index 00000000000..eaa91165161 --- /dev/null +++ b/dlls/dcomp/target.c @@ -0,0 +1,129 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_target *impl_from_IDCompositionTarget(IDCompositionTarget *iface) +{ + return CONTAINING_RECORD(iface, struct composition_target, IDCompositionTarget_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_target_QueryInterface( + IDCompositionTarget *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionTarget)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_target_AddRef(IDCompositionTarget *iface) +{ + struct composition_target *factory = impl_from_IDCompositionTarget(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_target_Release(IDCompositionTarget *iface) +{ + struct composition_target *composition_target = impl_from_IDCompositionTarget(iface); + ULONG refcount = InterlockedDecrement(&composition_target->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(composition_target); + } + + return refcount; +} + + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_target_SetRoot( + IDCompositionTarget *iface, IDCompositionVisual *visual) +{ + FIXME("iface %p, visual %p stub!\n", iface, visual); + return E_NOTIMPL; +} + +static const struct IDCompositionTargetVtbl composition_target_vtbl = +{ + composition_target_QueryInterface, + composition_target_AddRef, + composition_target_Release, + composition_target_SetRoot +}; + +static HRESULT STDMETHODCALLTYPE composition_target_init(struct composition_target *composition_target) +{ + composition_target->IDCompositionTarget_iface.lpVtbl = &composition_target_vtbl; + composition_target->refcount = 1; + return S_OK; +} + +HRESULT create_composition_target(HWND hwnd, BOOL topmost, IDCompositionTarget **target) +{ + struct composition_target *composition_target; + HRESULT hr; + + if(!(composition_target = calloc(1, sizeof(*composition_target)))) + { + ERR("Failed to allocate composition target memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_target_init(composition_target); + if (FAILED(hr)) + { + WARN("Failed to initialize composition target, hr %#lx.\n", hr); + free(composition_target); + *target = NULL; + return hr; + } + + TRACE("Created composition target %p.\n", composition_target); + *target = &composition_target->IDCompositionTarget_iface; + + return S_OK; +} diff --git a/dlls/dcomp/tests/Makefile.in b/dlls/dcomp/tests/Makefile.in new file mode 100644 index 00000000000..115cb7e025d --- /dev/null +++ b/dlls/dcomp/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = dcomp.dll +IMPORTS = d3d11 dcomp ole32 user32 + +SOURCES = \ + dcomp.c diff --git a/dlls/dcomp/tests/dcomp.c b/dlls/dcomp/tests/dcomp.c new file mode 100644 index 00000000000..a3659592409 --- /dev/null +++ b/dlls/dcomp/tests/dcomp.c @@ -0,0 +1,166 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> + +#include "windef.h" +#include "initguid.h" +#include "d3d11_4.h" +#include "dcomp.h" +#include "wine/test.h" + +static ID3D11Device *create_d3d11_device(void) +{ + static const D3D_FEATURE_LEVEL default_feature_level[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + const D3D_FEATURE_LEVEL *feature_level; + unsigned int feature_level_count; + ID3D11Device *device; + + feature_level = default_feature_level; + feature_level_count = ARRAY_SIZE(default_feature_level); + + if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, + feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, + feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + if (SUCCEEDED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, + feature_level, feature_level_count, D3D11_SDK_VERSION, &device, NULL, NULL))) + return device; + + return NULL; +} + +static HRESULT create_window_and_device(HWND *hwnd, ID3D11Device **d3d11_device, IDXGIDevice **dxgi_device) +{ + HRESULT hr; + + WNDCLASSEXW wcx = + { + .cbSize = sizeof(WNDCLASSEXW), + .hInstance = GetModuleHandleW(NULL), + .lpszClassName = L"device_monitor", + .lpfnWndProc = DefWindowProcW, + }; + + RegisterClassExW(&wcx); + + *hwnd = CreateWindowW(wcx.lpszClassName, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + + hr = *hwnd ? S_OK : E_FAIL; + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + ShowWindow(*hwnd, SW_SHOWNORMAL); + UpdateWindow(*hwnd); + + *d3d11_device = create_d3d11_device(); + ok(*d3d11_device != NULL, "Failed to create D3D11 device\n"); + + hr = ID3D11Device_QueryInterface(*d3d11_device, &IID_IDXGIDevice, (void **)dxgi_device); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + return hr; +} + +static void test_CreateInstance2_DesktopDevice(void) +{ + HRESULT hr; + ID3D11Device *d3d11_device; + HWND hwnd; + IDXGIDevice *dxgi_device = NULL; + IDCompositionDesktopDevice *dcomp_device; + + hr = create_window_and_device(&hwnd, &d3d11_device, &dxgi_device); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = DCompositionCreateDevice2((IUnknown *)dxgi_device, + &IID_IDCompositionDesktopDevice, + (void **)&dcomp_device); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDCompositionDesktopDevice_Release(dcomp_device); + + IDXGIDevice_Release(dxgi_device); +} + +static void test_create_surface_and_target(void) +{ + HRESULT hr; + ID3D11Device *d3d11_device; + HWND hwnd; + IDXGIDevice *dxgi_device = NULL; + IDCompositionDesktopDevice *dcomp_device; + IDCompositionSurfaceFactory *surface_factory; + IDCompositionSurface *surface; + IDCompositionVirtualSurface *virtual_surface; + IDCompositionTarget *target; + + hr = create_window_and_device(&hwnd, &d3d11_device, &dxgi_device); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = DCompositionCreateDevice2((IUnknown *)dxgi_device, + &IID_IDCompositionDesktopDevice, + (void **)&dcomp_device); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDCompositionDesktopDevice_CreateSurfaceFactory( + dcomp_device, (IUnknown *)dxgi_device, &surface_factory); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDCompositionSurfaceFactory_CreateSurface( + surface_factory, 100, 100, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ALPHA_MODE_PREMULTIPLIED, &surface); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDCompositionSurface_Release(surface); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDCompositionSurfaceFactory_CreateVirtualSurface( + surface_factory, 100, 100, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_ALPHA_MODE_PREMULTIPLIED, &virtual_surface); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDCompositionVirtualSurface_Release(virtual_surface); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IDCompositionDesktopDevice_CreateTargetForHwnd(dcomp_device, hwnd, FALSE, &target); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDCompositionTarget_Release(target); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IDCompositionDesktopDevice_Release(dcomp_device); + + IDXGIDevice_Release(dxgi_device); +} + +START_TEST(dcomp) +{ + CoInitialize(NULL); + + test_CreateInstance2_DesktopDevice(); + test_create_surface_and_target(); + + CoUninitialize(); +} diff --git a/dlls/dcomp/visual2.c b/dlls/dcomp/visual2.c new file mode 100644 index 00000000000..74d81199d44 --- /dev/null +++ b/dlls/dcomp/visual2.c @@ -0,0 +1,277 @@ +/* + * Copyright 2025 Jaakko Hannikainen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include <stdarg.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "objidl.h" +#include "dxgi.h" +#include "wine/debug.h" +#include "dcomp.h" +#include "dcomp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dcomp); + +static inline struct composition_visual *impl_from_IDCompositionVisual2(IDCompositionVisual2 *iface) +{ + return CONTAINING_RECORD(iface, struct composition_visual, IDCompositionVisual2_iface); +} + +static HRESULT STDMETHODCALLTYPE STDMETHODCALLTYPE composition_visual_QueryInterface( + IDCompositionVisual2 *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IDCompositionVisual)) + { + IUnknown_AddRef(iface); + *out = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE composition_visual_AddRef(IDCompositionVisual2 *iface) +{ + struct composition_visual *factory = impl_from_IDCompositionVisual2(iface); + ULONG refcount = InterlockedIncrement(&factory->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE composition_visual_Release(IDCompositionVisual2 *iface) +{ + struct composition_visual *composition_visual = impl_from_IDCompositionVisual2(iface); + ULONG refcount = InterlockedDecrement(&composition_visual->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + { + free(composition_visual); + } + + return refcount; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetOffsetXAnimation( + IDCompositionVisual2 *iface, IDCompositionAnimation *animation) +{ + FIXME("iface %p animation %p stub!\n", iface, animation); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetOffsetX( + IDCompositionVisual2 *iface, float offset_x) +{ + FIXME("iface %p offset_x %.8e stub!\n", iface, offset_x); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetOffsetYAnimation( + IDCompositionVisual2 *iface, IDCompositionAnimation *animation) +{ + FIXME("iface %p animation %p stub!\n", iface, animation); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetOffsetY( + IDCompositionVisual2 *iface, float offset_y) +{ + FIXME("iface %p offset_y %.8e stub!\n", iface, offset_y); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetTransformObject( + IDCompositionVisual2 *iface, IDCompositionTransform *transform) +{ + FIXME("iface %p transform %p stub!\n", iface, transform); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetTransform( + IDCompositionVisual2 *iface, const D2D_MATRIX_3X2_F *matrix) +{ + FIXME("iface %p matrix %p stub!\n", iface, matrix); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetTransformParent( + IDCompositionVisual2 *iface, IDCompositionVisual *visual) +{ + FIXME("iface %p visual %p stub!\n", iface, visual); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetEffect( + IDCompositionVisual2 *iface, IDCompositionEffect *effect) +{ + FIXME("iface %p effect %p stub!\n", iface, effect); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetBitmapInterpolationMode( + IDCompositionVisual2 *iface, enum DCOMPOSITION_BITMAP_INTERPOLATION_MODE interpolation_mode) +{ + FIXME("iface %p interpolation_mode %d stub!\n", iface, interpolation_mode); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetBorderMode( + IDCompositionVisual2 *iface, enum DCOMPOSITION_BORDER_MODE border_mode) +{ + FIXME("iface %p border_mode %d stub!\n", iface, border_mode); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetClipObject( + IDCompositionVisual2 *iface, IDCompositionClip *clip) +{ + FIXME("iface %p clip %p stub!\n", iface, clip); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetClip( + IDCompositionVisual2 *iface, const D2D_RECT_F *rect) +{ + FIXME("iface %p rect %p stub!\n", iface, rect); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetContent( + IDCompositionVisual2 *iface, IUnknown *content) +{ + FIXME("iface %p content %p stub!\n", iface, content); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_AddVisual( + IDCompositionVisual2 *iface, IDCompositionVisual *visual, BOOL insert_above, + IDCompositionVisual *reference_visual) +{ + FIXME("iface %p visual %p insert_above %d reference_visual %p stub!\n", + iface, visual, insert_above, reference_visual); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_RemoveVisual( + IDCompositionVisual2 *iface, IDCompositionVisual *visual) +{ + FIXME("iface %p visual %p stub!\n", iface, visual); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_RemoveAllVisuals(IDCompositionVisual2 *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetCompositeMode( + IDCompositionVisual2 *iface, enum DCOMPOSITION_COMPOSITE_MODE composite_mode) +{ + FIXME("iface %p composite_mode %d stub!\n", iface, composite_mode); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetOpacityMode( + IDCompositionVisual2 *iface, enum DCOMPOSITION_OPACITY_MODE opacity_mode) +{ + FIXME("iface %p opacity_mode %d stub!\n", iface, opacity_mode); + return E_NOTIMPL; +} + +static HRESULT STDMETHODCALLTYPE composition_visual_SetBackFaceVisibility( + IDCompositionVisual2 *iface, enum DCOMPOSITION_BACKFACE_VISIBILITY visibility) +{ + FIXME("iface %p visibility %d stub!\n", iface, visibility); + return E_NOTIMPL; +} + +static const struct IDCompositionVisual2Vtbl composition_visual_vtbl = +{ + composition_visual_QueryInterface, + composition_visual_AddRef, + composition_visual_Release, + + /* IDCompositionVisual methods */ + composition_visual_SetOffsetXAnimation, + composition_visual_SetOffsetX, + composition_visual_SetOffsetYAnimation, + composition_visual_SetOffsetY, + composition_visual_SetTransformObject, + composition_visual_SetTransform, + composition_visual_SetTransformParent, + composition_visual_SetEffect, + composition_visual_SetBitmapInterpolationMode, + composition_visual_SetBorderMode, + composition_visual_SetClipObject, + composition_visual_SetClip, + composition_visual_SetContent, + composition_visual_AddVisual, + composition_visual_RemoveVisual, + composition_visual_RemoveAllVisuals, + composition_visual_SetCompositeMode, + + /* IDCompositionVisual2 methods */ + composition_visual_SetOpacityMode, + composition_visual_SetBackFaceVisibility, +}; + +static HRESULT STDMETHODCALLTYPE composition_visual_init(struct composition_visual *composition_visual) +{ + composition_visual->IDCompositionVisual2_iface.lpVtbl = &composition_visual_vtbl; + composition_visual->refcount = 1; + return S_OK; +} + +HRESULT create_composition_visual(IDCompositionVisual2 **visual) +{ + struct composition_visual *composition_visual; + HRESULT hr; + + if(!(composition_visual = calloc(1, sizeof(*composition_visual)))) + { + ERR("Failed to allocate composition visual memory.\n"); + return E_OUTOFMEMORY; + } + + hr = composition_visual_init(composition_visual); + if (FAILED(hr)) + { + WARN("Failed to initialize composition visual, hr %#lx.\n", hr); + free(composition_visual); + *visual = NULL; + return hr; + } + + TRACE("Created composition visual %p.\n", composition_visual); + *visual = &composition_visual->IDCompositionVisual2_iface; + + return S_OK; +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9839