├── 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 | --------------------------------------------------------------------------------