From 2353349fe5ad613f6efdb832daef19375acffb6c Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Sat, 13 Nov 2021 01:10:06 +0100 Subject: [PATCH 1/2] Introduce AtlasEngine - A new text rendering prototype (#11623) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces "AtlasEngine", a new text renderer based on DxEngine. But unlike it, DirectWrite and Direct2D are only used to rasterize glyphs. Blending and placing these glyphs into the target view is being done using Direct3D and a simple HLSL shader. Since this new renderer more aggressively assumes that the text is monospace, it simplifies the implementation: The viewport is divided into cells, and its data is stored as a simple matrix. Modifications to this matrix involve only simple pointer arithmetic and is easy to understand. But just like with DxEngine however, DirectWrite related code remains extremely complex and hard to understand. Supported features: * Basic text rendering with grayscale AA * Foreground and background colors * Emojis, including zero width joiners * Underline, dotted underline, strikethrough * Custom font axes and features * Selections * All cursor styles * Full alpha support for all colors * _Should_ work with Windows 7 Unsupported features: * A more conservative GPU memory usage The backing texture atlas for glyphs is grow-only and will not shrink. After 256MB of memory is used up (~20k glyphs) text output will be broken until the renderer is restarted. * ClearType * Remaining gridlines (left, right, top, bottom, double underline) * Hyperlinks don't get full underlines if hovered in WT * Softfonts * Non-default line renditions Performance: * Runs at up to native display refresh rate Unfortunately the frame rate often drops below refresh rate, due us fighting over the buffer lock with other parts of the application. * CPU consumption is up to halved compared to DxEngine AtlasEngine is still highly unoptimized. Glyph hashing consumes up to a third of the current CPU time. * No regressions in WT performance VT parsing and related buffer management takes up most of the CPU time (~85%), due to which the AtlasEngine can't show any further improvements. * ~2x improvement in raw text throughput in OpenConsole compared to DxEngine running at 144 FPS * ≥10x improvement in colored VT output in WT/OpenConsole compared to DxEngine running at 144 FPS --- .github/actions/spelling/allow/allow.txt | 11 +- .github/actions/spelling/excludes.txt | 1 + OpenConsole.sln | 43 + .../PublicTerminalCore.vcxproj | 3 + src/cascadia/TerminalControl/ControlCore.cpp | 48 +- src/cascadia/TerminalControl/ControlCore.h | 7 +- .../TerminalControl/ControlInteractivity.h | 1 + .../TerminalControl/IControlSettings.idl | 2 +- src/cascadia/TerminalControl/TermControl.cpp | 67 +- src/cascadia/TerminalControl/TermControl.h | 8 +- .../TerminalControlLib.vcxproj | 1 + .../TerminalCore/lib/terminalcore-lib.vcxproj | 3 + .../TerminalSettingsEditor/Profiles.cpp | 13 +- .../TerminalSettingsEditor/Profiles.h | 5 +- .../TerminalSettingsEditor/Profiles.idl | 2 + .../TerminalSettingsEditor/Profiles.xaml | 11 +- .../Resources/en-US/Resources.resw | 4 + .../TerminalSettingsModel/MTSMSettings.h | 3 +- .../TerminalSettingsModel/Profile.idl | 1 + .../TerminalSettings.cpp | 1 + .../TerminalSettingsModel/TerminalSettings.h | 1 + .../UnitTests_Control/MockControlSettings.h | 1 + src/features.xml | 10 + src/host/exe/Host.EXE.vcxproj | 3 + src/host/ft_fuzzer/Host.FuzzWrapper.vcxproj | 4 + src/host/ft_host/CJK_DbcsTests.cpp | 3 - src/host/globals.h | 7 +- src/host/settings.cpp | 11 +- src/host/settings.hpp | 11 +- src/host/ut_host/Host.UnitTests.vcxproj | 3 + src/interactivity/win32/lib/win32.LIB.vcxproj | 5 +- .../Interactivity.Win32.UnitTests.vcxproj | 5 +- .../UiaTextRangeTests.cpp | 4 - src/interactivity/win32/window.cpp | 41 +- src/propslib/RegistrySerialization.cpp | 5 +- src/renderer/atlas/AtlasEngine.api.cpp | 605 +++++++ src/renderer/atlas/AtlasEngine.cpp | 1458 +++++++++++++++++ src/renderer/atlas/AtlasEngine.h | 761 +++++++++ src/renderer/atlas/AtlasEngine.r.cpp | 460 ++++++ src/renderer/atlas/atlas.vcxproj | 55 + src/renderer/atlas/pch.cpp | 4 + src/renderer/atlas/pch.h | 52 + src/renderer/atlas/shader_ps.hlsl | 182 ++ src/renderer/atlas/shader_vs.hlsl | 17 + src/renderer/base/RenderEngineBase.cpp | 3 +- src/renderer/base/thread.cpp | 6 - src/renderer/base/thread.hpp | 2 - src/renderer/dx/CustomTextLayout.cpp | 8 +- src/renderer/dx/CustomTextRenderer.cpp | 1 + src/renderer/dx/DxRenderer.cpp | 35 +- src/renderer/dx/DxRenderer.hpp | 42 +- src/renderer/inc/IRenderEngine.hpp | 119 +- src/renderer/uia/UiaRenderer.cpp | 7 + src/renderer/uia/UiaRenderer.hpp | 29 +- src/renderer/vt/vtrenderer.hpp | 69 +- src/renderer/wddmcon/WddmConRenderer.hpp | 2 +- 56 files changed, 3966 insertions(+), 300 deletions(-) create mode 100644 src/renderer/atlas/AtlasEngine.api.cpp create mode 100644 src/renderer/atlas/AtlasEngine.cpp create mode 100644 src/renderer/atlas/AtlasEngine.h create mode 100644 src/renderer/atlas/AtlasEngine.r.cpp create mode 100644 src/renderer/atlas/atlas.vcxproj create mode 100644 src/renderer/atlas/pch.cpp create mode 100644 src/renderer/atlas/pch.h create mode 100644 src/renderer/atlas/shader_ps.hlsl create mode 100644 src/renderer/atlas/shader_vs.hlsl diff --git a/.github/actions/spelling/allow/allow.txt b/.github/actions/spelling/allow/allow.txt index 085ff6682..f23f8a581 100644 --- a/.github/actions/spelling/allow/allow.txt +++ b/.github/actions/spelling/allow/allow.txt @@ -1,12 +1,13 @@ apc +Apc +bsd calt ccmp changelog -cybersecurity -Apc clickable clig copyable +cybersecurity dalet dcs Dcs @@ -34,17 +35,17 @@ It'd kje liga lje -locl -lorem Llast Lmid +locl +lorem Lorigin maxed mkmk mnt mru -noreply nje +noreply ogonek ok'd overlined diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt index 8d751a187..7d64932c9 100644 --- a/.github/actions/spelling/excludes.txt +++ b/.github/actions/spelling/excludes.txt @@ -61,6 +61,7 @@ SUMS$ ^src/host/runft\.bat$ ^src/host/runut\.bat$ ^src/interactivity/onecore/BgfxEngine\. +^src/renderer/atlas/ ^src/renderer/wddmcon/WddmConRenderer\. ^src/terminal/adapter/ut_adapter/run\.bat$ ^src/terminal/parser/delfuzzpayload\.bat$ diff --git a/OpenConsole.sln b/OpenConsole.sln index 493cba041..d1f99131d 100644 --- a/OpenConsole.sln +++ b/OpenConsole.sln @@ -400,6 +400,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests", EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AuditMode|Any CPU = AuditMode|Any CPU @@ -3339,6 +3341,46 @@ Global {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64 {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32 {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32 + {8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3438,6 +3480,7 @@ Global {C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E} {9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD} + {8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271} diff --git a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj index 1665034e1..a7063bb9b 100644 --- a/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj +++ b/src/cascadia/PublicTerminalCore/PublicTerminalCore.vcxproj @@ -29,6 +29,9 @@ {18D09A24-8240-42D6-8CB6-236EEE820263} + + {8222900C-8B6C-452A-91AC-BE95DB04B95F} + {af0a096a-8b3a-4949-81ef-7df8f0fee91f} diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index a402a2d5e..b08e4c474 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -3,16 +3,18 @@ #include "pch.h" #include "ControlCore.h" -#include + #include #include #include -#include #include #include + +#include "EventArgs.h" #include "../../types/inc/GlyphWidth.hpp" -#include "../../types/inc/Utils.hpp" #include "../../buffer/out/search.h" +#include "../../renderer/atlas/AtlasEngine.h" +#include "../../renderer/dx/DxRenderer.hpp" #include "ControlCore.g.cpp" @@ -202,6 +204,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation const double actualHeight, const double compositionScale) { + assert(_settings); + _panelWidth = actualWidth; _panelHeight = actualHeight; _compositionScale = compositionScale; @@ -222,10 +226,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation return false; } - // Set up the DX Engine - auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); - _renderer->AddRenderEngine(dxEngine.get()); - _renderEngine = std::move(dxEngine); + if (Feature_AtlasEngine::IsEnabled() && _settings.UseAtlasEngine()) + { + _renderEngine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>(); + } + else + { + _renderEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); + } + + _renderer->AddRenderEngine(_renderEngine.get()); // Initialize our font with the renderer // We don't have to care about DPI. We'll get a change message immediately if it's not 96 @@ -271,11 +281,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); _renderEngine->SetIntenseIsBold(_settings.IntenseIsBold()); - _updateAntiAliasingMode(_renderEngine.get()); + _updateAntiAliasingMode(); // GH#5098: Inform the engine of the opacity of the default text background. // GH#11315: Always do this, even if they don't have acrylic on. - _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(_settings.Opacity())); + const auto backgroundIsOpaque = _settings.Opacity() == 1.0 && _settings.BackgroundImage().empty(); + _renderEngine->SetDefaultTextBackgroundOpacity(static_cast(backgroundIsOpaque)); THROW_IF_FAILED(_renderEngine->Enable()); @@ -616,7 +627,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation _renderEngine->SetForceFullRepaintRendering(_settings.ForceFullRepaintRendering()); _renderEngine->SetSoftwareRendering(_settings.SoftwareRendering()); - _updateAntiAliasingMode(_renderEngine.get()); + _updateAntiAliasingMode(); // Refresh our font with the renderer const auto actualFontOldSize = _actualFont.GetSize(); @@ -650,22 +661,24 @@ namespace winrt::Microsoft::Terminal::Control::implementation } } - void ControlCore::_updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine) + void ControlCore::_updateAntiAliasingMode() { - // Update DxEngine's AntialiasingMode + D2D1_TEXT_ANTIALIAS_MODE mode; + switch (_settings.AntialiasingMode()) { case TextAntialiasingMode::Cleartype: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE); + mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; break; case TextAntialiasingMode::Aliased: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED); + mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED; break; - case TextAntialiasingMode::Grayscale: default: - dxEngine->SetAntialiasingMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE); + mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; break; } + + _renderEngine->SetAntialiasingMode(mode); } // Method Description: @@ -1296,7 +1309,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (_renderEngine) { auto lock = _terminal->LockForWriting(); - _renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast(opacity)); + const auto backgroundIsOpaque = opacity == 1.0 && _settings.BackgroundImage().empty(); + _renderEngine->SetDefaultTextBackgroundOpacity(static_cast(backgroundIsOpaque)); } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index 5beebf9e9..e9fca4644 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -15,11 +15,8 @@ #pragma once -#include "EventArgs.h" #include "ControlCore.g.h" #include "../../renderer/base/Renderer.hpp" -#include "../../renderer/dx/DxRenderer.hpp" -#include "../../renderer/uia/UiaRenderer.hpp" #include "../../cascadia/TerminalCore/Terminal.hpp" #include "../buffer/out/search.h" #include "cppwinrt_utils.h" @@ -188,7 +185,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation // As _renderer has a dependency on _renderEngine (through a raw pointer) // we must ensure the _renderer is deallocated first. // (C++ class members are destroyed in reverse order.) - std::unique_ptr<::Microsoft::Console::Render::DxEngine> _renderEngine{ nullptr }; + std::unique_ptr<::Microsoft::Console::Render::IRenderEngine> _renderEngine{ nullptr }; std::unique_ptr<::Microsoft::Console::Render::Renderer> _renderer{ nullptr }; IControlSettings _settings{ nullptr }; @@ -248,7 +245,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation #pragma endregion void _raiseReadOnlyWarning(); - void _updateAntiAliasingMode(::Microsoft::Console::Render::DxEngine* const dxEngine); + void _updateAntiAliasingMode(); void _connectionOutputHandler(const hstring& hstr); void _updateHoveredCell(const std::optional terminalPosition); diff --git a/src/cascadia/TerminalControl/ControlInteractivity.h b/src/cascadia/TerminalControl/ControlInteractivity.h index 71312afc3..5dd818d9d 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.h +++ b/src/cascadia/TerminalControl/ControlInteractivity.h @@ -22,6 +22,7 @@ #include "cppwinrt_utils.h" #include "ControlCore.h" +#include "../../renderer/uia/UiaRenderer.hpp" namespace ControlUnitTests { diff --git a/src/cascadia/TerminalControl/IControlSettings.idl b/src/cascadia/TerminalControl/IControlSettings.idl index 2b16e7334..e51a34c56 100644 --- a/src/cascadia/TerminalControl/IControlSettings.idl +++ b/src/cascadia/TerminalControl/IControlSettings.idl @@ -31,7 +31,7 @@ namespace Microsoft.Terminal.Control Boolean UseAcrylic; ScrollbarState ScrollState; - + Boolean UseAtlasEngine; String FontFace; Int32 FontSize; Windows.UI.Text.FontWeight FontWeight; diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 7da2257b4..25fd6d2d4 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -3,17 +3,16 @@ #include "pch.h" #include "TermControl.h" -#include -#include + #include #include -#include #include + +#include "TermControlAutomationPeer.h" #include "../../types/inc/GlyphWidth.hpp" -#include "../../types/inc/Utils.hpp" +#include "../../renderer/atlas/AtlasEngine.h" #include "TermControl.g.cpp" -#include "TermControlAutomationPeer.h" using namespace ::Microsoft::Console::Types; using namespace ::Microsoft::Console::VirtualTerminal; @@ -1828,13 +1827,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const winrt::Windows::Foundation::Size initialSize{ cols, rows }; - return GetProposedDimensions(initialSize, - settings.FontSize(), - settings.FontWeight(), - settings.FontFace(), - settings.ScrollState(), - settings.Padding(), - dpi); + return GetProposedDimensions(settings, dpi, initialSize); } // Function Description: @@ -1855,16 +1848,15 @@ namespace winrt::Microsoft::Terminal::Control::implementation // caller knows what monitor the control is about to appear on. // Return Value: // - a size containing the requested dimensions in pixels. - winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars, - const int32_t& fontHeight, - const winrt::Windows::UI::Text::FontWeight& fontWeight, - const winrt::hstring& fontFace, - const ScrollbarState& scrollState, - const winrt::hstring& padding, - const uint32_t dpi) + winrt::Windows::Foundation::Size TermControl::GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars) { const auto cols = ::base::saturated_cast(initialSizeInChars.Width); const auto rows = ::base::saturated_cast(initialSizeInChars.Height); + const auto fontSize = settings.FontSize(); + const auto fontWeight = settings.FontWeight(); + const auto fontFace = settings.FontFace(); + const auto scrollState = settings.ScrollState(); + const auto padding = settings.Padding(); // Initialize our font information. // The font width doesn't terribly matter, we'll only be using the @@ -1873,28 +1865,39 @@ namespace winrt::Microsoft::Terminal::Control::implementation // The family is only used to determine if the font is truetype or // not, but DX doesn't use that info at all. // The Codepage is additionally not actually used by the DX engine at all. - FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast(fontHeight) }, CP_UTF8, false }; + FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, gsl::narrow_cast(fontSize) }, CP_UTF8, false }; FontInfoDesired desiredFont = { actualFont }; // Create a DX engine and initialize it with our font and DPI. We'll // then use it to measure how much space the requested rows and columns // will take up. // TODO: MSFT:21254947 - use a static function to do this instead of - // instantiating a DxEngine + // instantiating a DxEngine/AtlasEngine. // GH#10211 - UNDER NO CIRCUMSTANCE should this fail. If it does, the // whole app will crash instantaneously on launch, which is no good. - auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); - LOG_IF_FAILED(dxEngine->UpdateDpi(dpi)); - LOG_IF_FAILED(dxEngine->UpdateFont(desiredFont, actualFont)); + double scale; + if (Feature_AtlasEngine::IsEnabled() && settings.UseAtlasEngine()) + { + auto engine = std::make_unique<::Microsoft::Console::Render::AtlasEngine>(); + LOG_IF_FAILED(engine->UpdateDpi(dpi)); + LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont)); + scale = engine->GetScaling(); + } + else + { + auto engine = std::make_unique<::Microsoft::Console::Render::DxEngine>(); + LOG_IF_FAILED(engine->UpdateDpi(dpi)); + LOG_IF_FAILED(engine->UpdateFont(desiredFont, actualFont)); + scale = engine->GetScaling(); + } - const auto scale = dxEngine->GetScaling(); - const auto fontSize = actualFont.GetSize(); + const auto actualFontSize = actualFont.GetSize(); // UWP XAML scrollbars aren't guaranteed to be the same size as the // ComCtl scrollbars, but it's certainly close enough. const auto scrollbarSize = GetSystemMetricsForDpi(SM_CXVSCROLL, dpi); - double width = cols * fontSize.X; + double width = cols * actualFontSize.X; // Reserve additional space if scrollbar is intended to be visible if (scrollState == ScrollbarState::Visible) @@ -1902,7 +1905,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation width += scrollbarSize; } - double height = rows * fontSize.Y; + double height = rows * actualFontSize.Y; const auto thickness = ParseThicknessFromPadding(padding); // GH#2061 - make sure to account for the size the padding _will be_ scaled to width += scale * (thickness.Left + thickness.Right); @@ -1962,13 +1965,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation const winrt::Windows::Foundation::Size minSize{ 1, 1 }; const double scaleFactor = DisplayInformation::GetForCurrentView().RawPixelsPerViewPixel(); const auto dpi = ::base::saturated_cast(USER_DEFAULT_SCREEN_DPI * scaleFactor); - return GetProposedDimensions(minSize, - _settings.FontSize(), - _settings.FontWeight(), - _settings.FontFace(), - _settings.ScrollState(), - _settings.Padding(), - dpi); + return GetProposedDimensions(_settings, dpi, minSize); } } diff --git a/src/cascadia/TerminalControl/TermControl.h b/src/cascadia/TerminalControl/TermControl.h index 8f758fb69..cde51ec12 100644 --- a/src/cascadia/TerminalControl/TermControl.h +++ b/src/cascadia/TerminalControl/TermControl.h @@ -92,13 +92,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation void Settings(IControlSettings newSettings); static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi); - static Windows::Foundation::Size GetProposedDimensions(const winrt::Windows::Foundation::Size& initialSizeInChars, - const int32_t& fontSize, - const winrt::Windows::UI::Text::FontWeight& fontWeight, - const winrt::hstring& fontFace, - const ScrollbarState& scrollState, - const winrt::hstring& padding, - const uint32_t dpi); + static Windows::Foundation::Size GetProposedDimensions(IControlSettings const& settings, const uint32_t dpi, const winrt::Windows::Foundation::Size& initialSizeInChars); void BellLightOn(); diff --git a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj index 3ce1d8a52..a366650fc 100644 --- a/src/cascadia/TerminalControl/TerminalControlLib.vcxproj +++ b/src/cascadia/TerminalControl/TerminalControlLib.vcxproj @@ -147,6 +147,7 @@ + diff --git a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj index 9ced8ea9f..2f750978b 100644 --- a/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj +++ b/src/cascadia/TerminalCore/lib/terminalcore-lib.vcxproj @@ -37,6 +37,9 @@ {3ae13314-1939-4dfa-9c14-38ca0834050c} + + {8222900C-8B6C-452A-91AC-BE95DB04B95F} + {48d21369-3d7b-4431-9967-24e81292cf62} diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.cpp b/src/cascadia/TerminalSettingsEditor/Profiles.cpp index 6c507ecf4..9c476fc3b 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.cpp +++ b/src/cascadia/TerminalSettingsEditor/Profiles.cpp @@ -246,13 +246,9 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _profile.HasUnfocusedAppearance(); } - bool ProfileViewModel::EditableUnfocusedAppearance() + bool ProfileViewModel::EditableUnfocusedAppearance() const noexcept { - if constexpr (Feature_EditableUnfocusedAppearance::IsEnabled()) - { - return true; - } - return false; + return Feature_EditableUnfocusedAppearance::IsEnabled(); } bool ProfileViewModel::ShowUnfocusedAppearance() @@ -286,6 +282,11 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _unfocusedAppearanceViewModel; } + bool ProfileViewModel::AtlasEngineAvailable() const noexcept + { + return Feature_AtlasEngine::IsEnabled(); + } + bool ProfileViewModel::UseParentProcessDirectory() { return StartingDirectory().empty(); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.h b/src/cascadia/TerminalSettingsEditor/Profiles.h index 40ecd9c45..7c12d9752 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles.h @@ -61,12 +61,12 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation Editor::AppearanceViewModel DefaultAppearance(); Editor::AppearanceViewModel UnfocusedAppearance(); bool HasUnfocusedAppearance(); - bool EditableUnfocusedAppearance(); + bool EditableUnfocusedAppearance() const noexcept; bool ShowUnfocusedAppearance(); - void CreateUnfocusedAppearance(const Windows::Foundation::Collections::IMapView& schemes, const IHostedInWindow& windowRoot); void DeleteUnfocusedAppearance(); + bool AtlasEngineAvailable() const noexcept; WINRT_PROPERTY(bool, IsBaseLayer, false); @@ -95,6 +95,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput); OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing); OBSERVABLE_PROJECTED_SETTING(_profile, BellStyle); + OBSERVABLE_PROJECTED_SETTING(_profile, UseAtlasEngine); private: Model::Profile _profile; diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.idl b/src/cascadia/TerminalSettingsEditor/Profiles.idl index 5d45a612c..a4746d560 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.idl +++ b/src/cascadia/TerminalSettingsEditor/Profiles.idl @@ -32,6 +32,7 @@ namespace Microsoft.Terminal.Settings.Editor Boolean EditableUnfocusedAppearance { get; }; Boolean ShowUnfocusedAppearance { get; }; AppearanceViewModel UnfocusedAppearance { get; }; + Boolean AtlasEngineAvailable { get; }; void CreateUnfocusedAppearance(Windows.Foundation.Collections.IMapView Schemes, IHostedInWindow WindowRoot); void DeleteUnfocusedAppearance(); @@ -61,6 +62,7 @@ namespace Microsoft.Terminal.Settings.Editor OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SnapOnInput); OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, AltGrAliasing); OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Settings.Model.BellStyle, BellStyle); + OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAtlasEngine); } runtimeclass DeleteProfileEventArgs diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.xaml b/src/cascadia/TerminalSettingsEditor/Profiles.xaml index 230cfc2e8..c860578aa 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.xaml +++ b/src/cascadia/TerminalSettingsEditor/Profiles.xaml @@ -319,7 +319,7 @@ + Visibility="{x:Bind State.Profile.EditableUnfocusedAppearance}">