├── nuget
├── VERSION
├── CompositionSurfaceFactory.props
├── CompositionSurfaceFactory.targets
└── CompositionSurfaceFactory.nuspec
├── CompositionSurfaceFactory
├── pch.cpp
├── Robmikh.CompositionSurfaceFactory.def
├── packages.config
├── Lock.cpp
├── TextSurfaceRedrawnEventArgs.cpp
├── DeviceLostEventArgs.cpp
├── DeviceLostEventArgs.h
├── LockSession.cpp
├── TextSurfaceRedrawnEventArgs.h
├── LockSession.h
├── Lock.h
├── pch.h
├── direct3d11.interop.h
├── DeviceLostHelper.h
├── CompositionSurfaceFactory.vcxproj.filters
├── UriSurface.h
├── DeviceLostHelper.cpp
├── UriSurface.cpp
├── SurfaceUtilities.h
├── TextSurface.cpp
├── TextSurface.h
├── SurfaceFactory.h
├── SurfaceUtilities.cpp
├── Robmikh.CompositionSurfacFactory.idl
├── SurfaceFactory.cpp
└── CompositionSurfaceFactory.vcxproj
├── LICENSE
├── CompositionSurfaceFactory.sln
├── .gitattributes
├── README.md
└── .gitignore
/nuget/VERSION:
--------------------------------------------------------------------------------
1 | 0.8.3
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/pch.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
--------------------------------------------------------------------------------
/nuget/CompositionSurfaceFactory.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/Robmikh.CompositionSurfaceFactory.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
3 | DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
4 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/Lock.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Lock.h"
3 | #include "LockSession.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | Robmikh::CompositionSurfaceFactory::LockSession Lock::GetLockSession()
8 | {
9 | com_ptr lock;
10 | lock.copy_from(this);
11 | auto session = make(lock);
12 | return session;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/TextSurfaceRedrawnEventArgs.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "TextSurfaceRedrawnEventArgs.h"
3 |
4 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
5 | {
6 | TextSurfaceRedrawnEventArgs::TextSurfaceRedrawnEventArgs(
7 | API::TextSurface const& surface,
8 | API::SurfaceFactory const& surfaceFactory)
9 | {
10 | m_surface = surface;
11 | m_surfaceFactory = surfaceFactory;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/DeviceLostEventArgs.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "DeviceLostEventArgs.h"
3 |
4 | using namespace winrt;
5 | using namespace Windows::Graphics::DirectX::Direct3D11;
6 |
7 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
8 | {
9 | DeviceLostEventArgs::DeviceLostEventArgs(IDirect3DDevice device)
10 | {
11 | m_device = device;
12 | }
13 |
14 | IDirect3DDevice DeviceLostEventArgs::Device()
15 | {
16 | return m_device;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/DeviceLostEventArgs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DeviceLostEventArgs.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct DeviceLostEventArgs : DeviceLostEventArgsT
8 | {
9 | DeviceLostEventArgs(Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice device);
10 |
11 | Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice Device();
12 |
13 | private:
14 | Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice m_device{ nullptr };
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/LockSession.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "LockSession.h"
3 | #include "Lock.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | LockSession::LockSession(
8 | com_ptr lock)
9 | {
10 | m_lock = lock;
11 | m_lock->LockInternal();
12 | }
13 |
14 | void LockSession::Close()
15 | {
16 | auto expected = false;
17 | if (m_closed.compare_exchange_strong(expected, true))
18 | {
19 | m_lock->UnlockInternal();
20 | m_lock = nullptr;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/TextSurfaceRedrawnEventArgs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "TextSurfaceRedrawnEventArgs.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct TextSurfaceRedrawnEventArgs : TextSurfaceRedrawnEventArgsT
8 | {
9 | TextSurfaceRedrawnEventArgs(
10 | API::TextSurface const& surface,
11 | API::SurfaceFactory const& surfaceFactory);
12 |
13 | Robmikh::CompositionSurfaceFactory::TextSurface Surface() { return m_surface; }
14 | Robmikh::CompositionSurfaceFactory::SurfaceFactory SurfaceFactory() { return m_surfaceFactory; }
15 | private:
16 | API::TextSurface m_surface{ nullptr };
17 | API::SurfaceFactory m_surfaceFactory{ nullptr };
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/LockSession.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "LockSession.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct Lock;
8 |
9 | struct LockSession : LockSessionT
10 | {
11 | LockSession(winrt::com_ptr lock);
12 | ~LockSession() { Close(); }
13 |
14 | void Close();
15 |
16 | private:
17 | void CheckClosed()
18 | {
19 | if (m_closed.load() == true)
20 | {
21 | throw hresult_error(RO_E_CLOSED);
22 | }
23 | }
24 |
25 | private:
26 | winrt::com_ptr m_lock;
27 | std::atomic m_closed = false;
28 | };
29 | }
30 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/Lock.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Lock.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct Lock : LockT
8 | {
9 | Lock() { InitializeCriticalSection(&m_criticalSection); }
10 | ~Lock() { DeleteCriticalSection(&m_criticalSection); }
11 |
12 | Robmikh::CompositionSurfaceFactory::LockSession GetLockSession();
13 |
14 | void LockInternal() { EnterCriticalSection(&m_criticalSection); }
15 | void UnlockInternal() { LeaveCriticalSection(&m_criticalSection); }
16 |
17 | private:
18 | CRITICAL_SECTION m_criticalSection;
19 | };
20 | }
21 |
22 | namespace winrt::Robmikh::CompositionSurfaceFactory::factory_implementation
23 | {
24 | struct Lock : LockT
25 | {
26 | };
27 | }
28 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/pch.h:
--------------------------------------------------------------------------------
1 | //
2 | // pch.h
3 | // Header for platform projection include files
4 | //
5 |
6 | #pragma once
7 |
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | #include "direct3d11.interop.h"
32 |
33 | #include
34 | namespace API = winrt::Robmikh::CompositionSurfaceFactory;
35 |
--------------------------------------------------------------------------------
/nuget/CompositionSurfaceFactory.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | $(MSBuildThisFileDirectory)$(Platform)\Robmikh.CompositionSurfaceFactory.winmd
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 robmikh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/direct3d11.interop.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | extern "C"
5 | {
6 | HRESULT __stdcall CreateDirect3D11DeviceFromDXGIDevice(::IDXGIDevice* dxgiDevice,
7 | ::IInspectable** graphicsDevice);
8 |
9 | HRESULT __stdcall CreateDirect3D11SurfaceFromDXGISurface(::IDXGISurface* dgxiSurface,
10 | ::IInspectable** graphicsSurface);
11 | }
12 |
13 | struct __declspec(uuid("A9B3D012-3DF2-4EE3-B8D1-8695F457D3C1"))
14 | IDirect3DDxgiInterfaceAccess : ::IUnknown
15 | {
16 | virtual HRESULT __stdcall GetInterface(GUID const& id, void** object) = 0;
17 | };
18 |
19 | inline auto CreateDirect3DDevice(IDXGIDevice* dxgi_device)
20 | {
21 | winrt::com_ptr<::IInspectable> d3d_device;
22 | winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(dxgi_device, d3d_device.put()));
23 | return d3d_device.as();
24 | }
25 |
26 | inline auto CreateDirect3DSurface(IDXGISurface* dxgi_surface)
27 | {
28 | winrt::com_ptr<::IInspectable> d3d_surface;
29 | winrt::check_hresult(CreateDirect3D11SurfaceFromDXGISurface(dxgi_surface, d3d_surface.put()));
30 | return d3d_surface.as();
31 | }
32 |
33 | template
34 | auto GetDXGIInterfaceFromObject(winrt::Windows::Foundation::IInspectable const& object)
35 | {
36 | auto access = object.as();
37 | winrt::com_ptr result;
38 | winrt::check_hresult(access->GetInterface(winrt::guid_of(), result.put_void()));
39 | return result;
40 | }
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/DeviceLostHelper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "DeviceLostHelper.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct DeviceLostHelper : DeviceLostHelperT
8 | {
9 | DeviceLostHelper() = default;
10 | ~DeviceLostHelper() { StopWatchingCurrentDevice(); OnDeviceLostHandler = NULL; }
11 |
12 | Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice CurrentlyWatchedDevice() { return m_device; }
13 | void WatchDevice(Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice const& device);
14 | void StopWatchingCurrentDevice();
15 | winrt::event_token DeviceLost(Windows::Foundation::EventHandler const& handler) { return m_deviceLostEvent.add(handler); }
16 | void DeviceLost(winrt::event_token const& token) noexcept { m_deviceLostEvent.remove(token); }
17 |
18 | private:
19 | void RaiseDeviceLostEvent(Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice const& oldDevice);
20 |
21 | static void CALLBACK OnDeviceLost(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WAIT wait, TP_WAIT_RESULT waitResult);
22 | private:
23 | Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice m_device{ nullptr };
24 | winrt::event> m_deviceLostEvent;
25 |
26 | PTP_WAIT OnDeviceLostHandler = NULL;
27 | HANDLE m_eventHandle = NULL;
28 | DWORD m_cookie = NULL;
29 | };
30 | }
31 |
32 | namespace winrt::Robmikh::CompositionSurfaceFactory::factory_implementation
33 | {
34 | struct DeviceLostHelper : DeviceLostHelperT
35 | {
36 | };
37 | }
38 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/CompositionSurfaceFactory.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | accd3aa8-1ba0-4223-9bbe-0c431709210b
6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
7 |
8 |
9 | {926ab91d-31b4-48c3-b9a4-e681349f27f0}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29519.161
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CompositionSurfaceFactory", "CompositionSurfaceFactory\CompositionSurfaceFactory.vcxproj", "{155CA046-B55D-43FD-A222-5FEE8EACAF07}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|ARM64 = Debug|ARM64
12 | Debug|x64 = Debug|x64
13 | Debug|x86 = Debug|x86
14 | Release|ARM = Release|ARM
15 | Release|ARM64 = Release|ARM64
16 | Release|x64 = Release|x64
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|ARM.ActiveCfg = Debug|ARM
21 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|ARM.Build.0 = Debug|ARM
22 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|ARM64.ActiveCfg = Debug|ARM64
23 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|ARM64.Build.0 = Debug|ARM64
24 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|x64.ActiveCfg = Debug|x64
25 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|x64.Build.0 = Debug|x64
26 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|x86.ActiveCfg = Debug|Win32
27 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Debug|x86.Build.0 = Debug|Win32
28 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|ARM.ActiveCfg = Release|ARM
29 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|ARM.Build.0 = Release|ARM
30 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|ARM64.ActiveCfg = Release|ARM64
31 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|ARM64.Build.0 = Release|ARM64
32 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|x64.ActiveCfg = Release|x64
33 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|x64.Build.0 = Release|x64
34 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|x86.ActiveCfg = Release|Win32
35 | {155CA046-B55D-43FD-A222-5FEE8EACAF07}.Release|x86.Build.0 = Release|Win32
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | GlobalSection(ExtensibilityGlobals) = postSolution
41 | SolutionGuid = {52D2BE46-DD75-4E94-A4EC-FA56F2537E2E}
42 | EndGlobalSection
43 | EndGlobal
44 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/UriSurface.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "UriSurface.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct UriSurface : UriSurfaceT
8 | {
9 | UriSurface(
10 | API::SurfaceFactory const& surfaceFactory,
11 | Windows::Foundation::Uri const& uri,
12 | Windows::Foundation::Size const size,
13 | API::InterpolationMode const interpolation);
14 | ~UriSurface() { Close(); }
15 |
16 | Windows::UI::Composition::Compositor Compositor() { CheckClosed(); return m_surfaceFactory.Compositor(); }
17 | Robmikh::CompositionSurfaceFactory::SurfaceFactory SurfaceFactory() { CheckClosed(); return m_surfaceFactory; }
18 | Windows::UI::Composition::ICompositionSurface Surface() { CheckClosed(); return m_surface; }
19 | Windows::Foundation::Uri Source() { CheckClosed(); return m_uri; }
20 | Windows::Foundation::Size Size();
21 | Robmikh::CompositionSurfaceFactory::InterpolationMode InterpolationMode() { CheckClosed(); return m_interpolationMode; }
22 | Windows::Foundation::IAsyncAction RedrawSurfaceAsync();
23 | Windows::Foundation::IAsyncAction RedrawSurfaceAsync(Windows::Foundation::Uri const uri);
24 | Windows::Foundation::IAsyncAction RedrawSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size);
25 | Windows::Foundation::IAsyncAction RedrawSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size, Robmikh::CompositionSurfaceFactory::InterpolationMode const interpolation);
26 | void Resize(Windows::Foundation::Size const& size);
27 | void Close();
28 |
29 | private:
30 | void CheckClosed()
31 | {
32 | if (m_closed.load() == true)
33 | {
34 | throw hresult_error(RO_E_CLOSED);
35 | }
36 | }
37 |
38 | fire_and_forget OnDeviceReplaced(winrt::Windows::Foundation::IInspectable const& sender, Windows::UI::Composition::RenderingDeviceReplacedEventArgs const& args);
39 |
40 | private:
41 | API::SurfaceFactory m_surfaceFactory{ nullptr };
42 | Windows::UI::Composition::CompositionDrawingSurface m_surface{ nullptr };
43 | Windows::Foundation::Uri m_uri{ nullptr };
44 | API::InterpolationMode m_interpolationMode;
45 | Windows::Foundation::Size m_size;
46 | API::SurfaceFactory::DeviceReplaced_revoker m_deviceReplaced;
47 | std::atomic m_closed = false;
48 | };
49 | }
50 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/DeviceLostHelper.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "DeviceLostHelper.h"
3 | #include "DeviceLostEventArgs.h"
4 |
5 | using namespace winrt;
6 | using namespace Windows::Foundation;
7 | using namespace Windows::Graphics::DirectX::Direct3D11;
8 |
9 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
10 | {
11 | void DeviceLostHelper::WatchDevice(
12 | IDirect3DDevice const& device)
13 | {
14 | // Stop listening for device lost if we currently are
15 | StopWatchingCurrentDevice();
16 |
17 | // Set the current device to the new device
18 | m_device = device;
19 |
20 | // Get the D3D Device
21 | auto d3dDevice = GetDXGIInterfaceFromObject(device);
22 |
23 | // Create a wait struct
24 | OnDeviceLostHandler = {};
25 | OnDeviceLostHandler = CreateThreadpoolWait(DeviceLostHelper::OnDeviceLost, (PVOID)this, NULL);
26 |
27 | // Create a handle and a cookie
28 | m_eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
29 | m_cookie = NULL;
30 |
31 | // Register for device lost
32 | SetThreadpoolWait(OnDeviceLostHandler, m_eventHandle, NULL);
33 | check_hresult(d3dDevice->RegisterDeviceRemovedEvent(m_eventHandle, &m_cookie));
34 | }
35 |
36 | void DeviceLostHelper::StopWatchingCurrentDevice()
37 | {
38 | if (m_device)
39 | {
40 | // Get the D3D Device
41 | auto d3dDevice = GetDXGIInterfaceFromObject(m_device);
42 |
43 | // Unregister from device lost
44 | CloseThreadpoolWait(OnDeviceLostHandler);
45 | d3dDevice->UnregisterDeviceRemoved(m_cookie);
46 |
47 | // Clear member variables
48 | OnDeviceLostHandler = NULL;
49 | CloseHandle(m_eventHandle);
50 | m_eventHandle = NULL;
51 | m_cookie = NULL;
52 | m_device = nullptr;
53 | }
54 | }
55 |
56 | void DeviceLostHelper::RaiseDeviceLostEvent(
57 | IDirect3DDevice const& oldDevice)
58 | {
59 | if (m_deviceLostEvent)
60 | {
61 | m_deviceLostEvent(*this, make(oldDevice));
62 | }
63 | }
64 |
65 | void CALLBACK DeviceLostHelper::OnDeviceLost(
66 | PTP_CALLBACK_INSTANCE instance,
67 | PVOID context,
68 | PTP_WAIT wait,
69 | TP_WAIT_RESULT waitResult)
70 | {
71 | UNREFERENCED_PARAMETER(instance);
72 | UNREFERENCED_PARAMETER(wait);
73 | UNREFERENCED_PARAMETER(waitResult);
74 |
75 | auto deviceLostHelper = reinterpret_cast(context);
76 | auto oldDevice = deviceLostHelper->m_device;
77 | deviceLostHelper->StopWatchingCurrentDevice();
78 |
79 | deviceLostHelper->RaiseDeviceLostEvent(oldDevice);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/UriSurface.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "UriSurface.h"
3 | #include "SurfaceUtilities.h"
4 |
5 | using namespace winrt;
6 | using namespace Windows::Foundation;
7 | using namespace Windows::UI;
8 | using namespace Windows::UI::Composition;
9 |
10 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
11 | {
12 | UriSurface::UriSurface(
13 | API::SurfaceFactory const& surfaceFactory,
14 | Uri const& uri,
15 | Windows::Foundation::Size const size,
16 | API::InterpolationMode const interpolation)
17 | {
18 | m_surfaceFactory = surfaceFactory;
19 | m_uri = uri;
20 | m_size = size;
21 | m_interpolationMode = interpolation;
22 |
23 | m_surface = m_surfaceFactory.CreateSurface(m_size);
24 | m_deviceReplaced = m_surfaceFactory.DeviceReplaced(auto_revoke, { this, &UriSurface::OnDeviceReplaced });
25 | }
26 |
27 | Windows::Foundation::Size UriSurface::Size()
28 | {
29 | CheckClosed();
30 | if (m_surface != nullptr)
31 | {
32 | return m_surface.Size();
33 | }
34 | else
35 | {
36 | return { 0, 0 };
37 | }
38 | }
39 |
40 | Windows::Foundation::IAsyncAction UriSurface::RedrawSurfaceAsync()
41 | {
42 | CheckClosed();
43 | co_await RedrawSurfaceAsync(m_uri);
44 | }
45 |
46 | Windows::Foundation::IAsyncAction UriSurface::RedrawSurfaceAsync(Windows::Foundation::Uri const uri)
47 | {
48 | CheckClosed();
49 | co_await RedrawSurfaceAsync(m_uri, m_size);
50 | }
51 |
52 | Windows::Foundation::IAsyncAction UriSurface::RedrawSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size)
53 | {
54 | CheckClosed();
55 | co_await RedrawSurfaceAsync(m_uri, m_size, m_interpolationMode);
56 | }
57 |
58 | Windows::Foundation::IAsyncAction UriSurface::RedrawSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size, Robmikh::CompositionSurfaceFactory::InterpolationMode const interpolation)
59 | {
60 | CheckClosed();
61 | m_uri = uri;
62 | m_interpolationMode = interpolation;
63 | m_size = size;
64 |
65 | if (m_uri != nullptr)
66 | {
67 | co_await implementation::SurfaceUtilities::FillSurfaceWithUriAsync(m_surfaceFactory, m_surface, m_uri, m_size, m_interpolationMode);
68 | }
69 | else
70 | {
71 | implementation::SurfaceUtilities::FillSurfaceWithColor(m_surfaceFactory, m_surface, Colors::Transparent(), m_size);
72 | }
73 | }
74 |
75 | void UriSurface::Resize(Windows::Foundation::Size const& size)
76 | {
77 | CheckClosed();
78 | m_surfaceFactory.ResizeSurface(m_surface, size);
79 | }
80 |
81 | void UriSurface::Close()
82 | {
83 | auto expected = false;
84 | if (m_closed.compare_exchange_strong(expected, true))
85 | {
86 | m_deviceReplaced.revoke();
87 | m_surface.Close();
88 | m_surface = nullptr;
89 | m_surfaceFactory = nullptr;
90 | m_uri = nullptr;
91 | }
92 | }
93 |
94 | fire_and_forget UriSurface::OnDeviceReplaced(
95 | winrt::Windows::Foundation::IInspectable const&,
96 | RenderingDeviceReplacedEventArgs const& args)
97 | {
98 | co_await RedrawSurfaceAsync();
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/nuget/CompositionSurfaceFactory.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Robmikh.CompositionSurfaceFactory
5 | 0.0.0-SpecifyVersionOnCommandline
6 | Robmikh.CompositionSurfaceFactory
7 | Robert Mikhayelyan
8 | Robert Mikhayelyan
9 | https://opensource.org/licenses/MIT
10 | https://github.com/robmikh/compositionsurfacefactory
11 | http://robmikh.com/compimageloader.png
12 | true
13 | CompositionSurfaceFactory is a surface factory intended for use with the Windows.UI.Composition API based on Win2D and written with C++/WinRT. Automatic image loading and text.
14 | Release notes:
15 | Version 0.8.3:
16 | * Add ARM64 support
17 |
18 | Version 0.8.2:
19 | * Minor fixes to C++/WinRT version
20 | * First C++/WinRT-based release!
21 |
22 | Version 0.8.1-prerelease:
23 | * Switch release mechanism (no code change)
24 |
25 | Version 0.8.0-prerelease:
26 | * Port to C++/WinRT
27 |
28 |
29 | Copyright 2016
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/SurfaceUtilities.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "SurfaceUtilities.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct SurfaceUtilities : SurfaceUtilitiesT
8 | {
9 | SurfaceUtilities() = delete;
10 |
11 |
12 | static void FillSurfaceWithColor(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::UI::Color const& color, Windows::Foundation::Size const& size);
13 | static void FillSurfaceWithColor(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::UI::Color const& color);
14 | static void FillSurfaceWithDirect3DSurface(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface const& direct3DSurface, Windows::Foundation::Size const& size, Robmikh::CompositionSurfaceFactory::InterpolationMode const& interpolation);
15 | static void FillSurfaceWithDirect3DSurface(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface const& direct3DSurface, Windows::Foundation::Size const& size);
16 | static void FillSurfaceWithDirect3DSurface(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface const& direct3DSurface);
17 | static Windows::Foundation::IAsyncAction FillSurfaceWithUriAsync(Robmikh::CompositionSurfaceFactory::SurfaceFactory const surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const surface, Windows::Foundation::Uri const uri, Windows::Foundation::Size const size, Robmikh::CompositionSurfaceFactory::InterpolationMode const interpolation);
18 | static Windows::Foundation::IAsyncAction FillSurfaceWithUriAsync(Robmikh::CompositionSurfaceFactory::SurfaceFactory const surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const surface, Windows::Foundation::Uri const uri, Windows::Foundation::Size const size);
19 | static Windows::Foundation::IAsyncAction FillSurfaceWithUriAsync(Robmikh::CompositionSurfaceFactory::SurfaceFactory const surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const surface, Windows::Foundation::Uri const uri);
20 | static void FillSurfaceWithBytes(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, array_view bytes, int32_t widthInPixels, int32_t heightInPixels, Windows::Foundation::Size const& size, Robmikh::CompositionSurfaceFactory::InterpolationMode const& interpolation);
21 | static void FillSurfaceWithBytes(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, array_view bytes, int32_t widthInPixels, int32_t heightInPixels, Windows::Foundation::Size const& size);
22 | static void FillSurfaceWithBytes(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, array_view bytes, int32_t widthInPixels, int32_t heightInPixels);
23 |
24 | private:
25 | static void FillSurfaceWithCanvasBitmap(Robmikh::CompositionSurfaceFactory::SurfaceFactory const& surfaceFactory, Windows::UI::Composition::CompositionDrawingSurface const& surface, Microsoft::Graphics::Canvas::CanvasBitmap const& bitmap, Windows::Foundation::Size const& size, Robmikh::CompositionSurfaceFactory::InterpolationMode const& interpolation);
26 | };
27 | }
28 |
29 | namespace winrt::Robmikh::CompositionSurfaceFactory::factory_implementation
30 | {
31 | struct SurfaceUtilities : SurfaceUtilitiesT
32 | {
33 | };
34 | }
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CompositionSurfaceFactory
2 | CompositionSurfaceFactory is a surface factory intended for use with the Windows.UI.Composition api based on Win2D and written with C++/WinRT. Don't worry, image loading still comes out of the box!
3 |
4 | ## Nuget Package
5 | You can download the latest nuget package for CompositionSurfaceFactory using this command:
6 | ```
7 | PM> Install-Package Robmikh.CompositionSurfaceFactory -Pre
8 | ```
9 | Learn more [here](https://www.nuget.org/packages/Robmikh.CompositionSurfaceFactory).
10 |
11 | ## Usage
12 |
13 | ### UriSurface
14 | UriSurface is just a wrapper to the CompositionDrawingSurface class which handles device lost events raised by the SurfaceFactory. When created with CreateUriSurface, the function will return immediately with a surface that is initialy empty and will be filled in asynchronously. When created with CreateUriSurfaceAsync the surface will be created and the image will be decoded at the same time. This means that when you get the surface back it is guaranteed to be filled in.
15 |
16 | ```
17 | var uriSurface = _surfaceFactory.CreateUriSurface(new Uri("ms-appx:///Assets/Images/testimage.png"));
18 | //
19 | // Consuming the real surface
20 | //
21 | visual.Brush = _compositor.CreateSurfaceBrush(uriSurface.Surface);
22 | ```
23 | When you're done with the UriSurface, just call Dispose() to let it unregister from SurfaceFactory's DeviceReplaced event. It is important to note that a UriSurface is "tethered" to a SurfaceFactory, as it is dependent on the SurfaceFactory to be able to redraw its surface. If you call Dispose() on the SurfaceFactory, any UriSurfaces that were created with that SurfaceFactory won't be able to redraw and will throw an exception when asked.
24 |
25 | You can also ask a UriSurface to redraw its contents at any time, and even provide a new Uri for it to use (and hold onto for the purposes of DeviceLost events).
26 |
27 | ### TextSurface
28 | TextSurface is very similar to UriSurface in that they are both wrappers to the CompositionDrawingSurface class which handle device lost events raised by the SurfaceFactory. However, TextSurface doesn’t get its contents from an image, but rather draws its own contents based on a given String. TextSurface also allows you to specify font, font size, font style, wrapping, and color by leveraging Win2D’s TextLayout APIs. Using TextSurface is easy:
29 |
30 | ```
31 | var textSurface = _surfaceFactory.CreateTextSurface("Hello, World!");
32 | //
33 | // Consuming the real surface
34 | //
35 | visual.Brush = _compositor.CreateSurfaceBrush(textSurface.Surface);
36 | ```
37 |
38 | It's important to note that changing properties tells the TextSurface to redraw, so if you're going to do a lot of customization, it might be wise to do most of it at creation time:
39 |
40 | ```
41 | var textSurface= _surfaceFactory.CreateTextSurface(reallyLongString, // Text
42 | 250.0f, // Desired Width
43 | 0.0f, // Desired Height
44 | "Times New Roman", // Font Family
45 | 14.0f, // Font Size
46 | FontStyle.Normal, // Font Style
47 | TextHorizontalAlignment.Left, // Horizontal Alignment
48 | TextVerticalAlignment.Top, // Vertical Alignment
49 | WordWrapping.WholeWord, // Wrapping
50 | new Padding(), // Padding
51 | Colors.DarkRed, // Foreground Color
52 | Colors.Transparent); // Background Color
53 | ```
54 |
55 | Finally, changing properties on the fly after creation could impact the new size of the surface, so a SurfaceRedrawn event has been exposed. This way you can always make sure your text is displayed correctly:
56 |
57 | ```
58 | textSurface.SurfaceRedrawn += (s, a) =>
59 | {
60 | visual.Size = textSurface.Size.ToVector2();
61 | };
62 | textSurface.FontSize = 30.0f;
63 | ```
64 |
65 | Just like with UriSurface, don't forget to dispose of TextSurface when you're done!
66 |
67 | ### Device Lost and Device Lifetime
68 | A device lost event is exposed to the caller through the SurfaceFactory. When notified of a device lost, the caller should ask the SurfaceFactory to redraw any needed surfaces. UriSurface and TextSurface will do this for you if used.
69 |
70 | When the SurfaceFactory is created with only a Compositor, it will create a new `CanvasDevice`. As such, the SurfaceFactory will be responsible for device lifetime, which includes creating and disposing of the device. Alternatively, if a CompositoinGraphicsDevice is given to the SurfaceFactory instead, then the caller is responsible for the device's lifetime.
71 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/TextSurface.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "TextSurface.h"
3 | #include "TextSurfaceRedrawnEventArgs.h"
4 |
5 | using namespace winrt;
6 | using namespace Windows::Foundation;
7 | using namespace Windows::UI;
8 | using namespace Windows::UI::Composition;
9 | using namespace Windows::UI::Text;
10 | using namespace Microsoft::Graphics::Canvas;
11 | using namespace Microsoft::Graphics::Canvas::UI::Composition;
12 | using namespace Microsoft::Graphics::Canvas::Text;
13 |
14 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
15 | {
16 | TextSurface::TextSurface(
17 | API::SurfaceFactory const& surfaceFactory,
18 | hstring const& text,
19 | float width,
20 | float height,
21 | hstring const& fontFamily,
22 | float fontSize,
23 | Windows::UI::Text::FontStyle const& fontStyle,
24 | API::TextHorizontalAlignment const& horizontalAlignment,
25 | API::TextVerticalAlignment const& verticalAlignment,
26 | API::WordWrapping const& wordWrapping,
27 | API::Padding const& padding,
28 | Color const& foregroundColor,
29 | Color const& backgroundColor)
30 | {
31 | m_surfaceFactory = surfaceFactory;
32 | m_text = text;
33 |
34 | // We initialize the surface to the size of 1x1 becuase
35 | // we can't create a drawing session from an empty surface
36 | // and we need the session to create our first TextLayout.
37 | m_surface = m_surfaceFactory.CreateSurface({ 1, 1 });
38 | m_textFormat = CanvasTextFormat();
39 |
40 | m_width = width;
41 | m_height = height;
42 | m_padding = padding;
43 | m_foregroundColor = foregroundColor;
44 | m_backgroundColor = backgroundColor;
45 |
46 | m_textFormat.FontFamily(fontFamily);
47 | m_textFormat.FontSize(fontSize);
48 | m_textFormat.FontStyle(fontStyle);
49 | m_textFormat.HorizontalAlignment(static_cast(horizontalAlignment));
50 | m_textFormat.VerticalAlignment(static_cast(verticalAlignment));
51 | m_textFormat.WordWrapping(static_cast(wordWrapping));
52 |
53 | UpdateTextLayout();
54 |
55 | m_deviceReplaced = m_surfaceFactory.DeviceReplaced(auto_revoke, { this, &TextSurface::OnDeviceReplaced });
56 | }
57 |
58 | void TextSurface::RedrawSurface()
59 | {
60 | CheckClosed();
61 |
62 | auto lock = m_surfaceFactory.DrawingLock();
63 |
64 | {
65 | auto lockSession = lock.GetLockSession();
66 |
67 | // I thought it should be:
68 | //float width = m_textLayout.DrawBounds().Width + m_padding.Left + m_padding.Right;
69 | //float height = m_textLayout.DrawBounds().Height + m_padding.Top + m_padding.Bottom;
70 | // But it needs to be:
71 | float width = m_textLayout.DrawBounds().X + m_textLayout.DrawBounds().Width + m_padding.Left + m_padding.Right;
72 | float height = m_textLayout.DrawBounds().Y + m_textLayout.DrawBounds().Height + m_padding.Top + m_padding.Bottom;
73 | // The surface can't have any dimmension be 0, so make it at least 1.0f
74 | if (width < 1.0f)
75 | {
76 | width = 1.0f;
77 | }
78 | if (height < 1.0f)
79 | {
80 | height = 1.0f;
81 | }
82 | CanvasComposition::Resize(m_surface, { width, height });
83 | auto session = CanvasComposition::CreateDrawingSession(m_surface);
84 | session.Clear(m_backgroundColor);
85 | session.DrawTextLayout(m_textLayout, m_padding.Left, m_padding.Right, m_foregroundColor);
86 | }
87 |
88 | if (m_surfaceRedrawnEvent)
89 | {
90 | m_surfaceRedrawnEvent(*this, make(*this, m_surfaceFactory));
91 | }
92 | }
93 |
94 | void TextSurface::Close()
95 | {
96 | auto expected = false;
97 | if (m_closed.compare_exchange_strong(expected, true))
98 | {
99 | m_deviceReplaced.revoke();
100 | m_surface.Close();
101 | m_surface = nullptr;
102 | m_surfaceFactory = nullptr;
103 | m_text = nullptr;
104 | m_textLayout = nullptr;
105 | m_textFormat = nullptr;
106 | }
107 | }
108 |
109 | void TextSurface::UpdateTextLayout()
110 | {
111 | auto lock = m_surfaceFactory.DrawingLock();
112 |
113 | {
114 | auto lockSession = lock.GetLockSession();
115 | auto session = CanvasComposition::CreateDrawingSession(m_surface);
116 | m_textLayout = CanvasTextLayout(session, m_text, m_textFormat, m_width, m_height);
117 | }
118 | }
119 |
120 | void TextSurface::OnDeviceReplaced(
121 | winrt::Windows::Foundation::IInspectable const&,
122 | RenderingDeviceReplacedEventArgs const&)
123 | {
124 | RedrawSurface();
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
262 | /CompositionSurfaceFactory/Generated Files
263 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/TextSurface.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "TextSurface.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct TextSurface : TextSurfaceT
8 | {
9 | TextSurface(
10 | API::SurfaceFactory const& surfaceFactory,
11 | hstring const& text,
12 | float width,
13 | float height,
14 | hstring const& fontFamily,
15 | float fontSize,
16 | Windows::UI::Text::FontStyle const& fontStyle,
17 | API::TextHorizontalAlignment const& horizontalAlignment,
18 | API::TextVerticalAlignment const& verticalAlignment,
19 | API::WordWrapping const& wordWrapping,
20 | API::Padding const& padding,
21 | Windows::UI::Color const& foregroundColor,
22 | Windows::UI::Color const& backgroundColor);
23 | ~TextSurface() { Close(); }
24 |
25 | Windows::UI::Composition::Compositor Compositor() { CheckClosed(); return m_surfaceFactory.Compositor(); }
26 | Robmikh::CompositionSurfaceFactory::SurfaceFactory SurfaceFactory() { CheckClosed(); return m_surfaceFactory; }
27 | Windows::UI::Composition::ICompositionSurface Surface() { CheckClosed(); return m_surface; }
28 | Windows::Foundation::Size Size() { CheckClosed(); return m_surface == nullptr ? Windows::Foundation::Size{ 0, 0 } : m_surface.Size(); }
29 | hstring Text() { CheckClosed(); return m_text; }
30 | void Text(hstring const& value) { CheckClosed(); m_text = value; UpdateTextLayout(); RedrawSurface(); }
31 | float Width() { CheckClosed(); return m_width; }
32 | void Width(float value) { CheckClosed(); m_width = value; UpdateTextLayout(); RedrawSurface(); }
33 | float Height() { CheckClosed(); return m_height; }
34 | void Height(float value) { CheckClosed(); m_height = value; UpdateTextLayout(); RedrawSurface(); }
35 | hstring FontFamily() { CheckClosed(); return m_textFormat.FontFamily(); }
36 | void FontFamily(hstring const& value) { CheckClosed(); m_textFormat.FontFamily(value); UpdateTextLayout(); RedrawSurface(); }
37 | float FontSize() { CheckClosed(); return m_textFormat.FontSize(); }
38 | void FontSize(float value) { CheckClosed(); m_textFormat.FontSize(value); UpdateTextLayout(); RedrawSurface(); }
39 | Windows::UI::Text::FontStyle FontStyle() { CheckClosed(); return m_textFormat.FontStyle(); }
40 | void FontStyle(Windows::UI::Text::FontStyle const& value) { CheckClosed(); m_textFormat.FontStyle(value); UpdateTextLayout(); RedrawSurface(); }
41 | Robmikh::CompositionSurfaceFactory::TextHorizontalAlignment HorizontalAlignment() { CheckClosed(); return static_cast(m_textFormat.HorizontalAlignment()); }
42 | void HorizontalAlignment(Robmikh::CompositionSurfaceFactory::TextHorizontalAlignment const& value) { CheckClosed(); m_textFormat.HorizontalAlignment(static_cast(value)); UpdateTextLayout(); RedrawSurface(); }
43 | Robmikh::CompositionSurfaceFactory::TextVerticalAlignment VerticalAlignment() { CheckClosed(); return static_cast(m_textFormat.VerticalAlignment()); }
44 | void VerticalAlignment(Robmikh::CompositionSurfaceFactory::TextVerticalAlignment const& value) { CheckClosed(); m_textFormat.VerticalAlignment(static_cast(value)); UpdateTextLayout(); RedrawSurface(); }
45 | Robmikh::CompositionSurfaceFactory::WordWrapping WordWrapping() { CheckClosed(); return static_cast(m_textFormat.WordWrapping()); }
46 | void WordWrapping(Robmikh::CompositionSurfaceFactory::WordWrapping const& value) { CheckClosed(); m_textFormat.WordWrapping(static_cast(value)); UpdateTextLayout(); RedrawSurface(); }
47 | Robmikh::CompositionSurfaceFactory::Padding Padding() { CheckClosed(); return m_padding; }
48 | void Padding(Robmikh::CompositionSurfaceFactory::Padding const& value) { CheckClosed(); m_padding = value; RedrawSurface(); }
49 | Windows::UI::Color ForegroundColor() { CheckClosed(); return m_foregroundColor; }
50 | void ForegroundColor(Windows::UI::Color const& value) { CheckClosed(); m_foregroundColor = value; RedrawSurface(); }
51 | Windows::UI::Color BackgroundColor() { CheckClosed(); return m_backgroundColor; }
52 | void BackgroundColor(Windows::UI::Color const& value) { CheckClosed(); m_backgroundColor = value; RedrawSurface(); }
53 | void RedrawSurface();
54 | winrt::event_token SurfaceRedrawn(Windows::Foundation::EventHandler const& handler) { return m_surfaceRedrawnEvent.add(handler); }
55 | void SurfaceRedrawn(winrt::event_token const& token) noexcept { m_surfaceRedrawnEvent.remove(token); }
56 | void Close();
57 |
58 | private:
59 | void CheckClosed()
60 | {
61 | if (m_closed.load() == true)
62 | {
63 | throw hresult_error(RO_E_CLOSED);
64 | }
65 | }
66 |
67 | void UpdateTextLayout();
68 | void OnDeviceReplaced(winrt::Windows::Foundation::IInspectable const& sender, Windows::UI::Composition::RenderingDeviceReplacedEventArgs const& args);
69 |
70 | private:
71 | API::SurfaceFactory m_surfaceFactory{ nullptr };
72 | Windows::UI::Composition::CompositionDrawingSurface m_surface{ nullptr };
73 | hstring m_text;
74 | float m_width;
75 | float m_height;
76 | Microsoft::Graphics::Canvas::Text::CanvasTextFormat m_textFormat;
77 | API::Padding m_padding;
78 | Windows::UI::Color m_foregroundColor;
79 | Windows::UI::Color m_backgroundColor;
80 | Microsoft::Graphics::Canvas::Text::CanvasTextLayout m_textLayout{ nullptr };
81 |
82 | winrt::event> m_surfaceRedrawnEvent;
83 | API::SurfaceFactory::DeviceReplaced_revoker m_deviceReplaced;
84 | std::atomic m_closed = false;
85 | };
86 | }
87 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/SurfaceFactory.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "SurfaceFactory.g.h"
4 |
5 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
6 | {
7 | struct SurfaceFactory : SurfaceFactoryT
8 | {
9 | SurfaceFactory(
10 | Windows::UI::Composition::Compositor const& compositor,
11 | Robmikh::CompositionSurfaceFactory::SurfaceFactoryOptions const& options);
12 | SurfaceFactory(
13 | Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice,
14 | Robmikh::CompositionSurfaceFactory::Lock const& lock);
15 | ~SurfaceFactory() { Close(); }
16 |
17 | Windows::UI::Composition::Compositor Compositor() { CheckClosed(); return m_compositor; }
18 | Windows::UI::Composition::CompositionGraphicsDevice GraphicsDevice() { CheckClosed(); return m_graphicsDevice; }
19 | Robmikh::CompositionSurfaceFactory::Lock DrawingLock() { CheckClosed(); return m_lock; }
20 | Windows::UI::Composition::CompositionDrawingSurface CreateSurface(Windows::Foundation::Size const& size);
21 | void ResizeSurface(Windows::UI::Composition::CompositionDrawingSurface const& surface, Windows::Foundation::Size const& size);
22 | Robmikh::CompositionSurfaceFactory::UriSurface CreateUriSurface() { CheckClosed(); return CreateUriSurface(nullptr); }
23 | Robmikh::CompositionSurfaceFactory::UriSurface CreateUriSurface(Windows::Foundation::Uri const& uri) { CheckClosed(); return CreateUriSurface(uri, { 0, 0 }); }
24 | Robmikh::CompositionSurfaceFactory::UriSurface CreateUriSurface(Windows::Foundation::Uri const& uri, Windows::Foundation::Size const& size) { CheckClosed(); return CreateUriSurface(uri, size, API::InterpolationMode::Linear); }
25 | Robmikh::CompositionSurfaceFactory::UriSurface CreateUriSurface(Windows::Foundation::Uri const& uri, Windows::Foundation::Size const& size, Robmikh::CompositionSurfaceFactory::InterpolationMode const& interpolation);
26 | Windows::Foundation::IAsyncOperation CreateUriSurfaceAsync(Windows::Foundation::Uri const uri) { CheckClosed(); return co_await CreateUriSurfaceAsync(uri, { 0, 0 }); }
27 | Windows::Foundation::IAsyncOperation CreateUriSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size) { CheckClosed(); return co_await CreateUriSurfaceAsync(uri, size, API::InterpolationMode::Linear); }
28 | Windows::Foundation::IAsyncOperation CreateUriSurfaceAsync(Windows::Foundation::Uri const uri, Windows::Foundation::Size const size, Robmikh::CompositionSurfaceFactory::InterpolationMode const interpolation);
29 | Robmikh::CompositionSurfaceFactory::TextSurface CreateTextSurface() { CheckClosed(); return CreateTextSurface(L""); }
30 | Robmikh::CompositionSurfaceFactory::TextSurface CreateTextSurface(hstring const& text)
31 | {
32 | CheckClosed();
33 | return CreateTextSurface(
34 | text,
35 | 0,
36 | 0,
37 | L"Segoe UI",
38 | 14.0f,
39 | Windows::UI::Text::FontStyle::Normal,
40 | API::TextHorizontalAlignment::Left,
41 | API::TextVerticalAlignment::Top,
42 | API::WordWrapping::NoWrap,
43 | { 0, 0, 0, 0 },
44 | Windows::UI::Colors::Black(),
45 | Windows::UI::Colors::Transparent());
46 | }
47 | Robmikh::CompositionSurfaceFactory::TextSurface CreateTextSurface(hstring const& text, float width, float height, hstring const& fontFamily, float fontSize, Windows::UI::Text::FontStyle const& fontStyle, Robmikh::CompositionSurfaceFactory::TextHorizontalAlignment const& horizontalAlignment, Robmikh::CompositionSurfaceFactory::TextVerticalAlignment const& verticalAlignment, Robmikh::CompositionSurfaceFactory::WordWrapping const& wordWrapping, Robmikh::CompositionSurfaceFactory::Padding const& padding, Windows::UI::Color const& foregroundColor, Windows::UI::Color const& backgroundColor);
48 | winrt::event_token DeviceReplaced(Windows::Foundation::EventHandler const& handler) { CheckClosed(); return m_deviceReplacedEvent.add(handler); }
49 | void DeviceReplaced(winrt::event_token const& token) noexcept { CheckClosed(); m_deviceReplacedEvent.remove(token); }
50 | void Close();
51 |
52 | static Robmikh::CompositionSurfaceFactory::SurfaceFactory GetSharedSurfaceFactoryForCompositor(Windows::UI::Composition::Compositor const& compositor);
53 | static void ClearSharedSurfaceFactories();
54 | static Robmikh::CompositionSurfaceFactory::SurfaceFactory CreateFromCompositor(Windows::UI::Composition::Compositor const& compositor);
55 | static Robmikh::CompositionSurfaceFactory::SurfaceFactory CreateFromCompositor(Windows::UI::Composition::Compositor const& compositor, Robmikh::CompositionSurfaceFactory::SurfaceFactoryOptions const& options);
56 | static Robmikh::CompositionSurfaceFactory::SurfaceFactory CreateFromGraphicsDevice(Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice);
57 | static Robmikh::CompositionSurfaceFactory::SurfaceFactory CreateFromGraphicsDevice(Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice, Robmikh::CompositionSurfaceFactory::Lock const& lock);
58 |
59 | private:
60 | void CheckClosed()
61 | {
62 | if (m_closed.load() == true)
63 | {
64 | throw hresult_error(RO_E_CLOSED);
65 | }
66 | }
67 |
68 | void CreateDevice(API::SurfaceFactoryOptions const& options);
69 | void OnDeviceLost(winrt::Windows::Foundation::IInspectable const& sender, API::DeviceLostEventArgs const& args);
70 | void OnDeviceReplaced(Windows::UI::Composition::CompositionGraphicsDevice const& sender, Windows::UI::Composition::RenderingDeviceReplacedEventArgs const& args);
71 |
72 | private:
73 | Windows::UI::Composition::Compositor m_compositor{ nullptr };
74 | Microsoft::Graphics::Canvas::CanvasDevice m_canvasDevice{ nullptr };
75 | Windows::UI::Composition::CompositionGraphicsDevice m_graphicsDevice{ nullptr };
76 | API::Lock m_lock{ nullptr };
77 | bool m_isGraphicsDeviceCreator;
78 |
79 | API::DeviceLostHelper m_deviceLostHelper{ nullptr };
80 | API::DeviceLostHelper::DeviceLost_revoker m_deviceLost;
81 | winrt::event_token m_deviceReplacedToken;
82 | winrt::event> m_deviceReplacedEvent;
83 |
84 | std::atomic m_closed = false;
85 |
86 | static std::vector s_surfaceFactories;
87 | static API::Lock s_lock;
88 | };
89 | }
90 |
91 | namespace winrt::Robmikh::CompositionSurfaceFactory::factory_implementation
92 | {
93 | struct SurfaceFactory : SurfaceFactoryT
94 | {
95 | };
96 | }
97 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/SurfaceUtilities.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "SurfaceUtilities.h"
3 |
4 | using namespace winrt;
5 | using namespace Windows::Foundation;
6 | using namespace Windows::UI;
7 | using namespace Windows::UI::Composition;
8 | using namespace Windows::Graphics::DirectX;
9 | using namespace Windows::Graphics::DirectX::Direct3D11;
10 | using namespace Microsoft::Graphics::Canvas;
11 | using namespace Microsoft::Graphics::Canvas::UI::Composition;
12 |
13 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
14 | {
15 | void SurfaceUtilities::FillSurfaceWithColor(
16 | API::SurfaceFactory const& surfaceFactory,
17 | CompositionDrawingSurface const& surface,
18 | Color const& color,
19 | Size const& size)
20 | {
21 | auto lock = surfaceFactory.DrawingLock();
22 |
23 | // Make the size at least 1x1
24 | auto newSize = size;
25 | if (newSize.Width <= 0 && newSize.Height <= 0)
26 | {
27 | newSize = { 1, 1 };
28 | }
29 |
30 | // Resize the surface
31 | surfaceFactory.ResizeSurface(surface, newSize);
32 |
33 | // Clear the surface with the desired color
34 | // Because the drawing is done asynchronously and multiple threads could
35 | // be trying to get access to the device/surface at the same time, we need
36 | // to do any device/surface work under a lock.
37 | {
38 | auto lockSession = lock.GetLockSession();
39 |
40 | auto session = CanvasComposition::CreateDrawingSession(surface);
41 | session.Clear(color);
42 | }
43 | }
44 |
45 | void SurfaceUtilities::FillSurfaceWithColor(
46 | API::SurfaceFactory const& surfaceFactory,
47 | CompositionDrawingSurface const& surface,
48 | Color const& color)
49 | {
50 | FillSurfaceWithColor(
51 | surfaceFactory,
52 | surface,
53 | color,
54 | { 0, 0 });
55 | }
56 |
57 | void SurfaceUtilities::FillSurfaceWithDirect3DSurface(
58 | API::SurfaceFactory const& surfaceFactory,
59 | CompositionDrawingSurface const& surface,
60 | IDirect3DSurface const& direct3DSurface,
61 | Size const& size,
62 | InterpolationMode const& interpolation)
63 | {
64 | auto lock = surfaceFactory.DrawingLock();
65 | auto canvasDevice = CanvasComposition::GetCanvasDevice(surfaceFactory.GraphicsDevice());
66 |
67 | auto bitmap = CanvasBitmap::CreateFromDirect3D11Surface(canvasDevice, direct3DSurface);
68 |
69 | implementation::SurfaceUtilities::FillSurfaceWithCanvasBitmap(surfaceFactory, surface, bitmap, size, interpolation);
70 | }
71 |
72 | void SurfaceUtilities::FillSurfaceWithDirect3DSurface(
73 | API::SurfaceFactory const& surfaceFactory,
74 | CompositionDrawingSurface const& surface,
75 | IDirect3DSurface const& direct3DSurface,
76 | Size const& size)
77 | {
78 | FillSurfaceWithDirect3DSurface(
79 | surfaceFactory,
80 | surface,
81 | direct3DSurface,
82 | size,
83 | API::InterpolationMode::Linear);
84 | }
85 |
86 | void SurfaceUtilities::FillSurfaceWithDirect3DSurface(
87 | API::SurfaceFactory const& surfaceFactory,
88 | CompositionDrawingSurface const& surface,
89 | IDirect3DSurface const& direct3DSurface)
90 | {
91 | FillSurfaceWithDirect3DSurface(
92 | surfaceFactory,
93 | surface,
94 | direct3DSurface,
95 | { 0, 0 });
96 | }
97 |
98 | IAsyncAction SurfaceUtilities::FillSurfaceWithUriAsync(
99 | API::SurfaceFactory const surfaceFactory,
100 | CompositionDrawingSurface const surface,
101 | Uri const uri,
102 | Size const size,
103 | InterpolationMode const interpolation)
104 | {
105 | auto lock = surfaceFactory.DrawingLock();
106 | auto canvasDevice = CanvasComposition::GetCanvasDevice(surfaceFactory.GraphicsDevice());
107 |
108 | auto bitmap = co_await CanvasBitmap::LoadAsync(canvasDevice, uri);
109 |
110 | implementation::SurfaceUtilities::FillSurfaceWithCanvasBitmap(surfaceFactory, surface, bitmap, size, interpolation);
111 | }
112 |
113 | IAsyncAction SurfaceUtilities::FillSurfaceWithUriAsync(
114 | API::SurfaceFactory const surfaceFactory,
115 | CompositionDrawingSurface const surface,
116 | Uri const uri,
117 | Size const size)
118 | {
119 | co_await FillSurfaceWithUriAsync(
120 | surfaceFactory,
121 | surface,
122 | uri,
123 | size,
124 | API::InterpolationMode::Linear);
125 | }
126 |
127 | IAsyncAction SurfaceUtilities::FillSurfaceWithUriAsync(
128 | API::SurfaceFactory const surfaceFactory,
129 | CompositionDrawingSurface const surface,
130 | Uri const uri)
131 | {
132 | co_await FillSurfaceWithUriAsync(
133 | surfaceFactory,
134 | surface,
135 | uri,
136 | { 0, 0 });
137 | }
138 |
139 | void SurfaceUtilities::FillSurfaceWithBytes(
140 | API::SurfaceFactory const& surfaceFactory,
141 | CompositionDrawingSurface const& surface,
142 | array_view bytes,
143 | int32_t widthInPixels,
144 | int32_t heightInPixels,
145 | Size const& size,
146 | API::InterpolationMode const& interpolation)
147 | {
148 | auto lock = surfaceFactory.DrawingLock();
149 | auto canvasDevice = CanvasComposition::GetCanvasDevice(surfaceFactory.GraphicsDevice());
150 |
151 | auto bitmap = CanvasBitmap::CreateFromBytes(canvasDevice, bytes, widthInPixels, heightInPixels, DirectXPixelFormat::B8G8R8A8UIntNormalized);
152 |
153 | implementation::SurfaceUtilities::FillSurfaceWithCanvasBitmap(surfaceFactory, surface, bitmap, size, interpolation);
154 | }
155 |
156 | void SurfaceUtilities::FillSurfaceWithBytes(
157 | API::SurfaceFactory const& surfaceFactory,
158 | CompositionDrawingSurface const& surface,
159 | array_view bytes,
160 | int32_t widthInPixels,
161 | int32_t heightInPixels,
162 | Size const& size)
163 | {
164 | FillSurfaceWithBytes(
165 | surfaceFactory,
166 | surface,
167 | bytes,
168 | widthInPixels,
169 | heightInPixels,
170 | size,
171 | API::InterpolationMode::Linear);
172 | }
173 |
174 | void SurfaceUtilities::FillSurfaceWithBytes(
175 | API::SurfaceFactory const& surfaceFactory,
176 | CompositionDrawingSurface const& surface,
177 | array_view bytes,
178 | int32_t widthInPixels,
179 | int32_t heightInPixels)
180 | {
181 | FillSurfaceWithBytes(
182 | surfaceFactory,
183 | surface,
184 | bytes,
185 | widthInPixels,
186 | heightInPixels,
187 | { 0, 0 });
188 | }
189 |
190 | void SurfaceUtilities::FillSurfaceWithCanvasBitmap(
191 | API::SurfaceFactory const& surfaceFactory,
192 | CompositionDrawingSurface const& surface,
193 | CanvasBitmap const& bitmap,
194 | Size const& size,
195 | API::InterpolationMode const& interpolation)
196 | {
197 | auto lock = surfaceFactory.DrawingLock();
198 |
199 | // Determine the size of our bitmap
200 | Size bitmapSize = bitmap.Size();
201 |
202 | // If the caller did not specify a valid size, then make it the same size as the bitmap
203 | auto newSize = size;
204 | if (newSize.Width <= 0 && newSize.Height <= 0)
205 | {
206 | newSize = bitmapSize;
207 | }
208 |
209 | // Resize the surface
210 | surfaceFactory.ResizeSurface(surface, newSize);
211 |
212 | // Draw the bitmap into the surface
213 | // Because the drawing is done asynchronously and multiple threads could
214 | // be trying to get access to the device/surface at the same time, we need
215 | // to do any device/surface work under a lock.
216 | {
217 | auto lockSession = lock.GetLockSession();
218 |
219 | {
220 | auto session = CanvasComposition::CreateDrawingSession(surface);
221 | Rect surfaceRect = { 0, 0, newSize.Width, newSize.Height };
222 | Rect bitmapRect = { 0, 0, bitmapSize.Width, bitmapSize.Height };
223 | CanvasImageInterpolation canvasInterpolation = static_cast(interpolation);
224 | session.Clear(Colors::Transparent());
225 | session.DrawImage(bitmap, surfaceRect, bitmapRect, 1.0f, canvasInterpolation);
226 | }
227 | }
228 | }
229 | }
230 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/Robmikh.CompositionSurfacFactory.idl:
--------------------------------------------------------------------------------
1 | namespace Robmikh.CompositionSurfaceFactory
2 | {
3 | enum InterpolationMode
4 | {
5 | NearestNeighbor = 0,
6 | Linear = 1,
7 | Cubic = 2,
8 | MultiSampleLinear = 3,
9 | Anisotropic = 4,
10 | HighQualityCubic = 5,
11 | };
12 |
13 | enum TextHorizontalAlignment
14 | {
15 | Left = 0,
16 | Right = 1,
17 | Center = 2,
18 | Justified = 3,
19 | };
20 |
21 | enum TextVerticalAlignment
22 | {
23 | Top = 0,
24 | Bottom = 1,
25 | Center = 2,
26 | };
27 |
28 | enum WordWrapping
29 | {
30 | Wrap = 0,
31 | NoWrap = 1,
32 | EmergencyBreak = 2,
33 | WholeWord = 3,
34 | Character = 4,
35 | };
36 |
37 | struct Padding
38 | {
39 | Single Left;
40 | Single Right;
41 | Single Top;
42 | Single Bottom;
43 | };
44 |
45 | struct SurfaceFactoryOptions
46 | {
47 | Boolean UseSoftwareRenderer;
48 | };
49 |
50 | [interface_name("IDeviceLostEventArgs", FB1D2D1C-CC72-3058-8C0E-BD40EC3759B5)]
51 | [marshaling_behavior(agile)]
52 | [webhosthidden]
53 | runtimeclass DeviceLostEventArgs
54 | {
55 | Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice Device { get; };
56 | }
57 |
58 | [interface_name("IDeviceLostHelper", 5CE9D519-9F0B-32E1-9025-E903B349B635)]
59 | [marshaling_behavior(agile)]
60 | [threading(both)]
61 | [webhosthidden]
62 | runtimeclass DeviceLostHelper
63 | {
64 | DeviceLostHelper();
65 |
66 | Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice CurrentlyWatchedDevice { get; };
67 | void WatchDevice(Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice device);
68 | void StopWatchingCurrentDevice();
69 | event Windows.Foundation.EventHandler DeviceLost;
70 | }
71 |
72 | [interface_name("ILock", 4412292E-280C-3D29-AF11-EA4F54136126)]
73 | [marshaling_behavior(agile)]
74 | [webhosthidden]
75 | runtimeclass Lock
76 | {
77 | Lock();
78 |
79 | LockSession GetLockSession();
80 | }
81 |
82 | [interface_name("ILockSession", C3F6B3C7-5E1F-3B60-9D30-5D0FEBC72396)]
83 | [marshaling_behavior(agile)]
84 | [webhosthidden]
85 | runtimeclass LockSession : Windows.Foundation.IClosable
86 | {
87 | }
88 |
89 | [interface_name("ISurfaceFactory", 3745AC26-AD98-3890-83F7-77999B5393EA)]
90 | [static_name("ISurfaceFactoryStatics", 327B01FD-AE20-37D1-9C6F-960EFA993CB1)]
91 | [marshaling_behavior(agile)]
92 | [threading(both)]
93 | [webhosthidden]
94 | runtimeclass SurfaceFactory : Windows.Foundation.IClosable
95 | {
96 | Windows.UI.Composition.Compositor Compositor { get; };
97 | Windows.UI.Composition.CompositionGraphicsDevice GraphicsDevice { get; };
98 | Lock DrawingLock { get; };
99 | Windows.UI.Composition.CompositionDrawingSurface CreateSurface(Windows.Foundation.Size size);
100 | void ResizeSurface(Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Foundation.Size size);
101 | [default_overload]
102 | UriSurface CreateUriSurface();
103 | UriSurface CreateUriSurface(Windows.Foundation.Uri uri);
104 | UriSurface CreateUriSurface(Windows.Foundation.Uri uri, Windows.Foundation.Size size);
105 | UriSurface CreateUriSurface(Windows.Foundation.Uri uri, Windows.Foundation.Size size, Robmikh.CompositionSurfaceFactory.InterpolationMode interpolation);
106 | [default_overload]
107 | Windows.Foundation.IAsyncOperation CreateUriSurfaceAsync(Windows.Foundation.Uri uri);
108 | Windows.Foundation.IAsyncOperation CreateUriSurfaceAsync(Windows.Foundation.Uri uri, Windows.Foundation.Size size);
109 | Windows.Foundation.IAsyncOperation CreateUriSurfaceAsync(Windows.Foundation.Uri uri, Windows.Foundation.Size size, InterpolationMode interpolation);
110 | [default_overload]
111 | Robmikh.CompositionSurfaceFactory.TextSurface CreateTextSurface();
112 | Robmikh.CompositionSurfaceFactory.TextSurface CreateTextSurface(String text);
113 | Robmikh.CompositionSurfaceFactory.TextSurface CreateTextSurface(String text, Single width, Single height, String fontFamily, Single fontSize, Windows.UI.Text.FontStyle fontStyle, Robmikh.CompositionSurfaceFactory.TextHorizontalAlignment horizontalAlignment, Robmikh.CompositionSurfaceFactory.TextVerticalAlignment verticalAlignment, Robmikh.CompositionSurfaceFactory.WordWrapping wordWrapping, Robmikh.CompositionSurfaceFactory.Padding padding, Windows.UI.Color foregroundColor, Windows.UI.Color backgroundColor);
114 | event Windows.Foundation.EventHandler DeviceReplaced;
115 |
116 | static SurfaceFactory GetSharedSurfaceFactoryForCompositor(Windows.UI.Composition.Compositor compositor);
117 | static void ClearSharedSurfaceFactories();
118 | [default_overload]
119 | static Robmikh.CompositionSurfaceFactory.SurfaceFactory CreateFromCompositor(Windows.UI.Composition.Compositor compositor);
120 | static Robmikh.CompositionSurfaceFactory.SurfaceFactory CreateFromCompositor(Windows.UI.Composition.Compositor compositor, SurfaceFactoryOptions options);
121 | [default_overload]
122 | static SurfaceFactory CreateFromGraphicsDevice(Windows.UI.Composition.CompositionGraphicsDevice graphicsDevice);
123 | static SurfaceFactory CreateFromGraphicsDevice(Windows.UI.Composition.CompositionGraphicsDevice graphicsDevice, Lock lock);
124 | }
125 |
126 | [interface_name("ISurfaceUtilities", 986C7CAC-619F-3A50-B83B-F039F575D397)]
127 | [static_name("ISurfaceUtilitiesStatics", 8E2E7797-D524-349F-BE77-D9CA47565DD8)]
128 | [marshaling_behavior(agile)]
129 | [webhosthidden]
130 | runtimeclass SurfaceUtilities
131 | {
132 | static void FillSurfaceWithColor(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.UI.Color color, Windows.Foundation.Size size);
133 | static void FillSurfaceWithColor(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.UI.Color color);
134 | static void FillSurfaceWithDirect3DSurface(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Graphics.DirectX.Direct3D11.IDirect3DSurface direct3DSurface, Windows.Foundation.Size size, Robmikh.CompositionSurfaceFactory.InterpolationMode interpolation);
135 | static void FillSurfaceWithDirect3DSurface(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Graphics.DirectX.Direct3D11.IDirect3DSurface direct3DSurface, Windows.Foundation.Size size);
136 | static void FillSurfaceWithDirect3DSurface(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Graphics.DirectX.Direct3D11.IDirect3DSurface direct3DSurface);
137 | static Windows.Foundation.IAsyncAction FillSurfaceWithUriAsync(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Foundation.Uri uri, Windows.Foundation.Size size, InterpolationMode interpolation);
138 | static Windows.Foundation.IAsyncAction FillSurfaceWithUriAsync(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Foundation.Uri uri, Windows.Foundation.Size size);
139 | static Windows.Foundation.IAsyncAction FillSurfaceWithUriAsync(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, Windows.Foundation.Uri uri);
140 | static void FillSurfaceWithBytes(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, UInt8[] bytes, Int32 widthInPixels, Int32 heightInPixels, Windows.Foundation.Size size, InterpolationMode interpolation);
141 | static void FillSurfaceWithBytes(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, UInt8[] bytes, Int32 widthInPixels, Int32 heightInPixels, Windows.Foundation.Size size);
142 | static void FillSurfaceWithBytes(SurfaceFactory surfaceFactory, Windows.UI.Composition.CompositionDrawingSurface surface, UInt8[] bytes, Int32 widthInPixels, Int32 heightInPixels);
143 | }
144 |
145 | [interface_name("ITextSurface", 1EF5CF55-3D43-3B2A-B824-A5BA5C988893)]
146 | [marshaling_behavior(agile)]
147 | [webhosthidden]
148 | runtimeclass TextSurface : Windows.Foundation.IClosable
149 | {
150 | Windows.UI.Composition.Compositor Compositor { get; };
151 | SurfaceFactory SurfaceFactory { get; };
152 | Windows.UI.Composition.ICompositionSurface Surface { get; };
153 | Windows.Foundation.Size Size { get; };
154 | String Text;
155 | Single Width;
156 | Single Height;
157 | String FontFamily;
158 | Single FontSize;
159 | Windows.UI.Text.FontStyle FontStyle;
160 | TextHorizontalAlignment HorizontalAlignment;
161 | TextVerticalAlignment VerticalAlignment;
162 | WordWrapping WordWrapping;
163 | Padding Padding;
164 | Windows.UI.Color ForegroundColor;
165 | Windows.UI.Color BackgroundColor;
166 | void RedrawSurface();
167 | event Windows.Foundation.EventHandler SurfaceRedrawn;
168 | }
169 |
170 | [interface_name("ITextSurfaceRedrawnEventArgs", B9DD2DDF-1CEB-3E08-836C-F8B1557EA7BF)]
171 | [marshaling_behavior(agile)]
172 | [webhosthidden]
173 | runtimeclass TextSurfaceRedrawnEventArgs
174 | {
175 | TextSurface Surface { get; };
176 | SurfaceFactory SurfaceFactory { get; };
177 | }
178 |
179 | [interface_name("IUriSurface", 4B6164AC-053F-3B85-AC01-18D0906B1E41)]
180 | [marshaling_behavior(agile)]
181 | [webhosthidden]
182 | runtimeclass UriSurface : Windows.Foundation.IClosable
183 | {
184 | Windows.UI.Composition.Compositor Compositor { get; };
185 | SurfaceFactory SurfaceFactory { get; };
186 | Windows.UI.Composition.ICompositionSurface Surface { get; };
187 | Windows.Foundation.Uri Source { get; };
188 | Windows.Foundation.Size Size { get; };
189 | InterpolationMode InterpolationMode { get; };
190 | [default_overload]
191 | Windows.Foundation.IAsyncAction RedrawSurfaceAsync();
192 | Windows.Foundation.IAsyncAction RedrawSurfaceAsync(Windows.Foundation.Uri uri);
193 | Windows.Foundation.IAsyncAction RedrawSurfaceAsync(Windows.Foundation.Uri uri, Windows.Foundation.Size size);
194 | Windows.Foundation.IAsyncAction RedrawSurfaceAsync(Windows.Foundation.Uri uri, Windows.Foundation.Size size, InterpolationMode interpolation);
195 | void Resize(Windows.Foundation.Size size);
196 | }
197 |
198 |
199 | }
200 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/SurfaceFactory.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "SurfaceFactory.h"
3 | #include "Lock.h"
4 | #include "UriSurface.h"
5 | #include "TextSurface.h"
6 | #include "DeviceLostHelper.h"
7 |
8 | using namespace winrt;
9 | using namespace Windows::Foundation;
10 | using namespace Windows::UI;
11 | using namespace Windows::UI::Composition;
12 | using namespace Windows::UI::Text;
13 | using namespace Microsoft::Graphics::Canvas;
14 | using namespace Microsoft::Graphics::Canvas::UI::Composition;
15 | using namespace Microsoft::Graphics::Canvas::Text;
16 |
17 | namespace winrt::Robmikh::CompositionSurfaceFactory::implementation
18 | {
19 | std::vector implementation::SurfaceFactory::s_surfaceFactories;
20 | API::Lock implementation::SurfaceFactory::s_lock = make();
21 |
22 | SurfaceFactory::SurfaceFactory(
23 | Windows::UI::Composition::Compositor const& compositor,
24 | API::SurfaceFactoryOptions const& options)
25 | {
26 | m_compositor = compositor;
27 | m_lock = make();
28 | m_isGraphicsDeviceCreator = true;
29 | m_deviceLostHelper = make();
30 | m_deviceLost = m_deviceLostHelper.DeviceLost(auto_revoke, { this, &SurfaceFactory::OnDeviceLost });
31 |
32 | CreateDevice(options);
33 | }
34 |
35 | SurfaceFactory::SurfaceFactory(
36 | Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice,
37 | API::Lock const& lock)
38 | {
39 | m_compositor = graphicsDevice.Compositor();
40 | m_graphicsDevice = graphicsDevice;
41 | m_isGraphicsDeviceCreator = false;
42 | if (lock == nullptr)
43 | {
44 | m_lock = make();
45 | }
46 | else
47 | {
48 | m_lock = lock;
49 | }
50 |
51 | m_deviceReplacedToken = m_graphicsDevice.RenderingDeviceReplaced({ this, &SurfaceFactory::OnDeviceReplaced });
52 | }
53 |
54 | CompositionDrawingSurface SurfaceFactory::CreateSurface(
55 | Size const& size)
56 | {
57 | auto surfaceSize = size;
58 | if (surfaceSize.Width <= 0 && surfaceSize.Height <= 0)
59 | {
60 | // We start out with a size of 0,0 for the surface, because we don't know
61 | // the size of the image at this time. We resize the surface later.
62 | surfaceSize = { 0, 0 };
63 | }
64 |
65 | CompositionDrawingSurface surface = nullptr;
66 |
67 | {
68 | auto lockSession = m_lock.GetLockSession();
69 | surface = m_graphicsDevice.CreateDrawingSurface(
70 | surfaceSize,
71 | Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
72 | Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
73 | }
74 |
75 | return surface;
76 | }
77 |
78 | void SurfaceFactory::ResizeSurface(
79 | CompositionDrawingSurface const& surface,
80 | Size const& size)
81 | {
82 | auto lockSession = m_lock.GetLockSession();
83 | CanvasComposition::Resize(surface, size);
84 | }
85 |
86 | API::UriSurface SurfaceFactory::CreateUriSurface(
87 | Uri const& uri,
88 | Size const& size,
89 | API::InterpolationMode const& interpolation)
90 | {
91 | auto uriSurface = make(*this, uri, size, interpolation);
92 | auto ignored = uriSurface.RedrawSurfaceAsync();
93 |
94 | return uriSurface;
95 | }
96 |
97 | IAsyncOperation SurfaceFactory::CreateUriSurfaceAsync(
98 | Uri const uri,
99 | Size const size,
100 | API::InterpolationMode const interpolation)
101 | {
102 | auto uriSurface = make(*this, uri, size, interpolation);
103 | co_await uriSurface.RedrawSurfaceAsync();
104 |
105 | return uriSurface;
106 | }
107 |
108 | API::TextSurface SurfaceFactory::CreateTextSurface(
109 | hstring const& text,
110 | float width,
111 | float height,
112 | hstring const& fontFamily,
113 | float fontSize,
114 | FontStyle const& fontStyle,
115 | API::TextHorizontalAlignment const& horizontalAlignment,
116 | API::TextVerticalAlignment const& verticalAlignment,
117 | API::WordWrapping const& wordWrapping,
118 | API::Padding const& padding,
119 | Color const& foregroundColor,
120 | Color const& backgroundColor)
121 | {
122 | auto textSurface = make(
123 | *this,
124 | text,
125 | width,
126 | height,
127 | fontFamily,
128 | fontSize,
129 | fontStyle,
130 | horizontalAlignment,
131 | verticalAlignment,
132 | wordWrapping,
133 | padding,
134 | foregroundColor,
135 | backgroundColor);
136 | textSurface.RedrawSurface();
137 |
138 | return textSurface;
139 | }
140 |
141 | void SurfaceFactory::CreateDevice(
142 | API::SurfaceFactoryOptions const& options)
143 | {
144 | if (m_compositor != nullptr && m_isGraphicsDeviceCreator)
145 | {
146 | if (m_canvasDevice == nullptr)
147 | {
148 | m_canvasDevice = CanvasDevice(options.UseSoftwareRenderer);
149 |
150 | m_deviceLostHelper.WatchDevice(m_canvasDevice);
151 | }
152 |
153 | if (m_graphicsDevice == nullptr)
154 | {
155 | m_graphicsDevice = CanvasComposition::CreateCompositionGraphicsDevice(m_compositor, m_canvasDevice);
156 | // The following doesn't work because the auto revoker requires the event source
157 | // to support weak refrences.
158 | //m_deviceReplaced = m_graphicsDevice.RenderingDeviceReplaced(auto_revoke, { this, &SurfaceFactory::OnDeviceReplaced });
159 | m_deviceReplacedToken = m_graphicsDevice.RenderingDeviceReplaced({ this, &SurfaceFactory::OnDeviceReplaced });
160 | }
161 | }
162 | }
163 |
164 | void SurfaceFactory::OnDeviceLost(
165 | winrt::Windows::Foundation::IInspectable const&,
166 | API::DeviceLostEventArgs const&)
167 | {
168 | bool softwareRenderer = m_canvasDevice.ForceSoftwareRenderer();
169 |
170 | m_canvasDevice = CanvasDevice(softwareRenderer);
171 | m_deviceLostHelper.WatchDevice(m_canvasDevice);
172 |
173 | CanvasComposition::SetCanvasDevice(m_graphicsDevice, m_canvasDevice);
174 | }
175 |
176 | void SurfaceFactory::OnDeviceReplaced(
177 | CompositionGraphicsDevice const&,
178 | RenderingDeviceReplacedEventArgs const& args)
179 | {
180 | if (m_deviceReplacedEvent)
181 | {
182 | m_deviceReplacedEvent(*this, args);
183 | }
184 | }
185 |
186 | void SurfaceFactory::Close()
187 | {
188 | auto expected = false;
189 | if (m_closed.compare_exchange_strong(expected, true))
190 | {
191 | {
192 | auto lockSession = m_lock.GetLockSession();
193 |
194 | m_compositor = nullptr;
195 | if (m_canvasDevice != nullptr)
196 | {
197 | m_deviceLost.revoke();
198 | m_deviceLostHelper.StopWatchingCurrentDevice();
199 | m_deviceLostHelper = nullptr;
200 |
201 | m_canvasDevice.Close();
202 | m_canvasDevice = nullptr;
203 | }
204 |
205 | if (m_graphicsDevice != nullptr)
206 | {
207 | m_graphicsDevice.RenderingDeviceReplaced(m_deviceReplacedToken);
208 | // Only dispose the composition graphics device if we own the device.
209 | if (m_isGraphicsDeviceCreator)
210 | {
211 | m_graphicsDevice.Close();
212 | }
213 | m_graphicsDevice = nullptr;
214 | }
215 |
216 | {
217 | auto listLockSession = s_lock.GetLockSession();
218 | auto index = std::find(std::begin(s_surfaceFactories), std::end(s_surfaceFactories), *this);
219 | if (index != std::end(s_surfaceFactories))
220 | {
221 | s_surfaceFactories.erase(index);
222 | }
223 | }
224 | }
225 | m_lock = nullptr;
226 | }
227 | }
228 |
229 | API::SurfaceFactory SurfaceFactory::GetSharedSurfaceFactoryForCompositor(
230 | Windows::UI::Composition::Compositor const& compositor)
231 | {
232 | API::SurfaceFactory result{ nullptr };
233 |
234 | // We do this under a lock so that it is safe for multiple callers on different threads. The
235 | // SurfaceFactory itself may also be changing the list when it is being destroyed.
236 | {
237 | auto lockSession = s_lock.GetLockSession();
238 |
239 | // Look to see if one of the surface factories is associated with the compositor
240 | for (auto& surfaceFactory : s_surfaceFactories)
241 | {
242 | if (surfaceFactory.Compositor() == compositor)
243 | {
244 | result = surfaceFactory;
245 | break;
246 | }
247 | }
248 |
249 | // If we didn't find one, then make one and add it to the list
250 | if (result == nullptr)
251 | {
252 | result = implementation::SurfaceFactory::CreateFromCompositor(compositor);
253 | s_surfaceFactories.push_back(result);
254 | }
255 | }
256 |
257 | return result;
258 | }
259 |
260 | void SurfaceFactory::ClearSharedSurfaceFactories()
261 | {
262 | std::vector copiedList;
263 |
264 | // We do this under a lock so that it is safe for multiple callers on different threads. The
265 | // SurfaceFactory itself may also be changing the list when it is being destroyed.
266 | {
267 | auto lockSession = s_lock.GetLockSession();
268 |
269 | // Copy the list so that when we are disposing the SurfaceFactory objects they don't
270 | // screw with the list as we are iterating through it.
271 | for (auto& surfaceFactory : s_surfaceFactories)
272 | {
273 | copiedList.push_back(surfaceFactory);
274 | }
275 | }
276 |
277 |
278 | // Dispose all the SurfaceFactories. This has to be done outside of the lock because the
279 | // SurfaceFactory will request the lock when disposing, and we would dead lock;
280 | for (auto& surfaceFactory : s_surfaceFactories)
281 | {
282 | surfaceFactory.Close();
283 | }
284 |
285 | {
286 | auto lockSession = s_lock.GetLockSession();
287 | s_surfaceFactories.clear();
288 | }
289 |
290 | copiedList.clear();
291 | }
292 |
293 | API::SurfaceFactory SurfaceFactory::CreateFromCompositor(
294 | Windows::UI::Composition::Compositor const& compositor)
295 | {
296 | auto options = API::SurfaceFactoryOptions();
297 | options.UseSoftwareRenderer = false;
298 |
299 | return implementation::SurfaceFactory::CreateFromCompositor(compositor, options);
300 | }
301 |
302 | API::SurfaceFactory SurfaceFactory::CreateFromCompositor(
303 | Windows::UI::Composition::Compositor const& compositor,
304 | API::SurfaceFactoryOptions const& options)
305 | {
306 | auto surfaceFactory = make(compositor, options);
307 | return surfaceFactory;
308 | }
309 |
310 | API::SurfaceFactory SurfaceFactory::CreateFromGraphicsDevice(
311 | Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice)
312 | {
313 | auto lock = make();
314 | return implementation::SurfaceFactory::CreateFromGraphicsDevice(graphicsDevice, lock);
315 | }
316 |
317 | API::SurfaceFactory SurfaceFactory::CreateFromGraphicsDevice(
318 | Windows::UI::Composition::CompositionGraphicsDevice const& graphicsDevice,
319 | API::Lock const& lock)
320 | {
321 | auto surfaceFactory = make(graphicsDevice, lock);
322 | return surfaceFactory;
323 | }
324 | }
325 |
--------------------------------------------------------------------------------
/CompositionSurfaceFactory/CompositionSurfaceFactory.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | true
7 | {155ca046-b55d-43fd-a222-5fee8eacaf07}
8 | CompositionSurfaceFactory
9 | Robmikh.CompositionSurfaceFactory
10 | en-US
11 | 14.0
12 | true
13 | Windows Store
14 | 10.0
15 | 10.0.18362.0
16 | 10.0.17134.0
17 |
18 |
19 |
20 |
21 | Debug
22 | ARM
23 |
24 |
25 | Debug
26 | ARM64
27 |
28 |
29 | Debug
30 | Win32
31 |
32 |
33 | Debug
34 | x64
35 |
36 |
37 | Release
38 | ARM
39 |
40 |
41 | Release
42 | ARM64
43 |
44 |
45 | Release
46 | Win32
47 |
48 |
49 | Release
50 | x64
51 |
52 |
53 |
54 | DynamicLibrary
55 | v142
56 | Unicode
57 | false
58 |
59 |
60 | true
61 | true
62 |
63 |
64 | false
65 | true
66 | false
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | $(RootNamespace)
79 |
80 |
81 | $(RootNamespace)
82 |
83 |
84 | $(RootNamespace)
85 |
86 |
87 | $(RootNamespace)
88 |
89 |
90 | $(RootNamespace)
91 |
92 |
93 | $(RootNamespace)
94 |
95 |
96 | $(RootNamespace)
97 |
98 |
99 | $(RootNamespace)
100 |
101 |
102 |
103 | Use
104 | pch.h
105 | $(IntDir)pch.pch
106 | Level4
107 | %(AdditionalOptions) /bigobj
108 | 28204
109 | _WINRT_DLL;%(PreprocessorDefinitions)
110 | $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
111 |
112 |
113 | Console
114 | true
115 | Robmikh.CompositionSurfaceFactory.def
116 |
117 |
118 |
119 |
120 | _DEBUG;%(PreprocessorDefinitions)
121 | Guard
122 | Guard
123 | Guard
124 | Guard
125 | ProgramDatabase
126 | ProgramDatabase
127 | ProgramDatabase
128 |
129 |
130 | $(OutDir)$(TargetName)$(TargetExt)
131 | $(OutDir)$(TargetName).pdb
132 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
133 |
134 |
135 | $(OutDir)$(TargetName)$(TargetExt)
136 | $(OutDir)$(TargetName).pdb
137 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
138 |
139 |
140 | $(OutDir)$(TargetName)$(TargetExt)
141 | $(OutDir)$(TargetName)$(TargetExt)
142 | $(OutDir)$(TargetName).pdb
143 | $(OutDir)$(TargetName).pdb
144 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
145 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
146 |
147 |
148 |
149 |
150 | NDEBUG;%(PreprocessorDefinitions)
151 | Guard
152 | Guard
153 | Guard
154 | Guard
155 | true
156 | true
157 | true
158 | true
159 |
160 |
161 | $(OutDir)$(TargetName)$(TargetExt)
162 | $(OutDir)$(TargetName).pdb
163 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
164 |
165 |
166 | $(OutDir)$(TargetName)$(TargetExt)
167 | $(OutDir)$(TargetName).pdb
168 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
169 |
170 |
171 | $(OutDir)$(TargetName)$(TargetExt)
172 | $(OutDir)$(TargetName)$(TargetExt)
173 | $(OutDir)$(TargetName).pdb
174 | $(OutDir)$(TargetName).pdb
175 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
176 | /PDBALTPATH:Robmikh.CompositionSurfaceFactory.pdb %(AdditionalOptions)
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | Create
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
222 |
223 |
224 |
225 |
226 |
227 |
--------------------------------------------------------------------------------