2020-01-03 15:25:21 +01:00
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
# pragma once
Move ConPTY to use til::bitmap (#5024)
## Summary of the Pull Request
Moves the ConPTY drawing mechanism (`VtRenderer`) to use the fine-grained `til::bitmap` individual-dirty-bit tracking mechanism instead of coarse-grained rectangle unions to improve drawing performance by dramatically reducing the total area redrawn.
## PR Checklist
* [x] Part of #778 and #1064
* [x] I work here
* [x] Tests added and updated.
* [x] I'm a core contributor
## Detailed Description of the Pull Request / Additional comments
- Converted `GetDirtyArea()` interface from `IRenderEngine` to use a vector of `til::rectangle` instead of the `SMALL_RECT` to banhammer inclusive rectangles.
- `VtEngine` now holds and operates on the `til::bitmap` for invalidation regions. All invalidation operation functions that used to be embedded inside `VtEngine` are deleted in favor of using the ones in `til::bitmap`.
- Updated `VtEngine` tracing to use new `til::bitmap` on trace and the new `to_string()` methods detailed below.
- Comparison operators for `til::bitmap` and complementary tests.
- Fixed an issue where the dirty rectangle shortcut in `til::bitmap` was set to 0,0,0,0 by default which means that `|=` on it with each `set()` operation was stretching the rectangle from 0,0. Now it's a `std::optional` so it has no value after just being cleared and will build from whatever the first invalidated rectangle is. Complementary tests added.
- Optional run caching for `til::bitmap` in the `runs()` method since both VT and DX renderers will likely want to generate the set of runs at the beginning of a frame and refer to them over and over through that frame. Saves the iteration and creation and caches inside `til::bitmap` where the chance of invalidation of the underlying data is known best. It is still possible to iterate manually with `begin()` and `end()` from the outside without caching, if desired. Complementary tests added.
- WEX templates added for `til::bitmap` and used in tests.
- `translate()` method for `til::bitmap` which will slide the dirty points in the direction specified by a `til::point` and optionally back-fill the uncovered area as dirty. Complementary tests added.
- Moves all string generation for `til` types `size`, `point`, `rectangle`, and `some` into a `to_string` method on each object such that it can be used in both ETW tracing scenarios AND in the TAEF templates uniformly. Adds a similar method for `bitmap`.
- Add tagging to `_bitmap_const_iterator` such that it appears as a valid **Input Iterator** to STL collections and can be used in a `std::vector` constructor as a range. Adds and cleans up operators on this iterator to match the theoretical requirements for an **Input Iterator**. Complementary tests added.
- Add loose operators to `til` which will allow some basic math operations (+, -, *, /) between `til::size` and `til::point` and vice versa. Complementary tests added. Complementary tests added.
- Adds operators to `til::rectangle` to allow scaling with basic math operations (+, -, *) versus `til::size` and translation with basic math operations (+, -) against `til::point`. Complementary tests added.
- In-place variants of some operations added to assorted `til` objects. Complementary tests added.
- Update VT tests to compare invalidation against the new map structure instead of raw rectangles where possible.
## Validation Steps Performed
- Wrote additional til Unit Tests for all additional operators and functions added to the project to support this operation
- Updated the existing VT renderer tests
- Ran perf check
2020-03-23 16:57:54 +01:00
# define _TIL_INLINEPREFIX __declspec(noinline) inline
2020-01-20 21:53:24 +01:00
# include "til/at.h"
2020-03-10 01:17:24 +01:00
# include "til/color.h"
2020-03-27 23:48:49 +01:00
# include "til/math.h"
2020-01-09 18:07:52 +01:00
# include "til/some.h"
2020-03-10 21:51:26 +01:00
# include "til/size.h"
2020-03-13 01:04:43 +01:00
# include "til/point.h"
Move ConPTY to use til::bitmap (#5024)
## Summary of the Pull Request
Moves the ConPTY drawing mechanism (`VtRenderer`) to use the fine-grained `til::bitmap` individual-dirty-bit tracking mechanism instead of coarse-grained rectangle unions to improve drawing performance by dramatically reducing the total area redrawn.
## PR Checklist
* [x] Part of #778 and #1064
* [x] I work here
* [x] Tests added and updated.
* [x] I'm a core contributor
## Detailed Description of the Pull Request / Additional comments
- Converted `GetDirtyArea()` interface from `IRenderEngine` to use a vector of `til::rectangle` instead of the `SMALL_RECT` to banhammer inclusive rectangles.
- `VtEngine` now holds and operates on the `til::bitmap` for invalidation regions. All invalidation operation functions that used to be embedded inside `VtEngine` are deleted in favor of using the ones in `til::bitmap`.
- Updated `VtEngine` tracing to use new `til::bitmap` on trace and the new `to_string()` methods detailed below.
- Comparison operators for `til::bitmap` and complementary tests.
- Fixed an issue where the dirty rectangle shortcut in `til::bitmap` was set to 0,0,0,0 by default which means that `|=` on it with each `set()` operation was stretching the rectangle from 0,0. Now it's a `std::optional` so it has no value after just being cleared and will build from whatever the first invalidated rectangle is. Complementary tests added.
- Optional run caching for `til::bitmap` in the `runs()` method since both VT and DX renderers will likely want to generate the set of runs at the beginning of a frame and refer to them over and over through that frame. Saves the iteration and creation and caches inside `til::bitmap` where the chance of invalidation of the underlying data is known best. It is still possible to iterate manually with `begin()` and `end()` from the outside without caching, if desired. Complementary tests added.
- WEX templates added for `til::bitmap` and used in tests.
- `translate()` method for `til::bitmap` which will slide the dirty points in the direction specified by a `til::point` and optionally back-fill the uncovered area as dirty. Complementary tests added.
- Moves all string generation for `til` types `size`, `point`, `rectangle`, and `some` into a `to_string` method on each object such that it can be used in both ETW tracing scenarios AND in the TAEF templates uniformly. Adds a similar method for `bitmap`.
- Add tagging to `_bitmap_const_iterator` such that it appears as a valid **Input Iterator** to STL collections and can be used in a `std::vector` constructor as a range. Adds and cleans up operators on this iterator to match the theoretical requirements for an **Input Iterator**. Complementary tests added.
- Add loose operators to `til` which will allow some basic math operations (+, -, *, /) between `til::size` and `til::point` and vice versa. Complementary tests added. Complementary tests added.
- Adds operators to `til::rectangle` to allow scaling with basic math operations (+, -, *) versus `til::size` and translation with basic math operations (+, -) against `til::point`. Complementary tests added.
- In-place variants of some operations added to assorted `til` objects. Complementary tests added.
- Update VT tests to compare invalidation against the new map structure instead of raw rectangles where possible.
## Validation Steps Performed
- Wrote additional til Unit Tests for all additional operators and functions added to the project to support this operation
- Updated the existing VT renderer tests
- Ran perf check
2020-03-23 16:57:54 +01:00
# include "til/operators.h"
2020-04-13 22:09:02 +02:00
# include "til/rectangle.h"
2020-03-19 17:10:13 +01:00
# include "til/bitmap.h"
2020-01-30 01:55:48 +01:00
# include "til/u8u16convert.h"
2020-01-09 18:07:52 +01:00
2020-01-03 15:25:21 +01:00
namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
2020-06-11 00:02:05 +02:00
template < typename T >
void manage_vector ( std : : vector < T > & vector , typename std : : vector < T > : : size_type requestedSize , float shrinkThreshold )
{
const auto existingCapacity = vector . capacity ( ) ;
const auto requiredCapacity = requestedSize ;
// Check by integer first as float math is way more expensive.
if ( requiredCapacity < existingCapacity )
{
// Now check if it's even worth shrinking. We don't want to shrink by 1 at a time, so meet a threshold first.
if ( requiredCapacity < = gsl : : narrow_cast < size_t > ( ( static_cast < float > ( existingCapacity ) * shrinkThreshold ) ) )
{
// There's no real way to force a shrink, so make a new one.
vector = std : : vector < T > { } ;
}
}
// Reserve won't shrink on its own and won't grow if we have enough space.
vector . reserve ( requiredCapacity ) ;
}
2020-01-03 15:25:21 +01:00
}
// These sit outside the namespace because they sit outside for WIL too.
// Inspired from RETURN_IF_WIN32_BOOL_FALSE
// WIL doesn't include a RETURN_BOOL_IF_FALSE, and RETURN_IF_WIN32_BOOL_FALSE
// will actually return the value of GLE.
# define RETURN_BOOL_IF_FALSE(b) \
do \
{ \
const bool __boolRet = wil : : verify_bool ( b ) ; \
if ( ! __boolRet ) \
{ \
return __boolRet ; \
} \
} while ( 0 , 0 )
// Due to a bug (DevDiv 441931), Warning 4297 (function marked noexcept throws exception) is detected even when the throwing code is unreachable, such as the end of scope after a return, in function-level catch.
# define CATCH_LOG_RETURN_FALSE() \
catch ( . . . ) \
{ \
__pragma ( warning ( suppress : 4297 ) ) ; \
LOG_CAUGHT_EXCEPTION ( ) ; \
return false ; \
}
2020-02-10 23:09:08 +01:00
// MultiByteToWideChar has a bug in it where it can return 0 and then not set last error.
// WIL has a fit if the last error is 0 when a bool false is returned.
// This macro doesn't have a fit. It just reports E_UNEXPECTED instead.
# define THROW_LAST_ERROR_IF_AND_IGNORE_BAD_GLE(condition) \
do \
{ \
if ( condition ) \
{ \
const auto gle = : : GetLastError ( ) ; \
if ( gle ) \
{ \
THROW_WIN32 ( gle ) ; \
} \
else \
{ \
THROW_HR ( E_UNEXPECTED ) ; \
} \
} \
} while ( 0 , 0 )