Move dirty interface to N rectangles, not just one (#4854)

## Summary of the Pull Request
- Changes the `IRenderEngine` interface to return a vector of values instead of just a single one. Engines that want to report one still can. Engines that want to report multiple smaller ones will be able to do so going forward.

## PR Checklist
* [x] In support of differential rendering #778
* [x] I work here.
* [x] Manually tested it still works.
* [x] Am core contributor.

## Detailed Description of the Pull Request / Additional comments
- Some of my ideas for the `DxEngine` require the ability to specify multiple smaller rectangles instead of one giant one, specifically to mitigate the case where someone refreshes just one cell in two opposite corners of the display (which currently coalesces into refreshing the entire display.)
- This is pulled out into an individual PR to make it easier to review that concept changing.

## Validation Steps Performed
- Ran the Terminal
This commit is contained in:
Michael Niksa 2020-03-10 13:31:46 -07:00 committed by GitHub
parent d954ad68f2
commit 2b6e96a745
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 93 additions and 73 deletions

View file

@ -232,7 +232,7 @@ BgfxEngine::BgfxEngine(PVOID SharedViewBase, LONG DisplayHeight, LONG DisplayWid
return S_OK; return S_OK;
} }
SMALL_RECT BgfxEngine::GetDirtyRectInChars() std::vector<SMALL_RECT> BgfxEngine::GetDirtyArea()
{ {
SMALL_RECT r; SMALL_RECT r;
r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0; r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0;
@ -240,7 +240,7 @@ SMALL_RECT BgfxEngine::GetDirtyRectInChars()
r.Left = 0; r.Left = 0;
r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0; r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0;
return r; return { r };
} }
[[nodiscard]] HRESULT BgfxEngine::GetFontSize(_Out_ COORD* const pFontSize) noexcept [[nodiscard]] HRESULT BgfxEngine::GetFontSize(_Out_ COORD* const pFontSize) noexcept

View file

@ -69,7 +69,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
SMALL_RECT GetDirtyRectInChars() override; std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;

View file

@ -563,7 +563,11 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
// This is effectively the number of cells on the visible screen that need to be redrawn. // This is effectively the number of cells on the visible screen that need to be redrawn.
// The origin is always 0, 0 because it represents the screen itself, not the underlying buffer. // The origin is always 0, 0 because it represents the screen itself, not the underlying buffer.
auto dirty = Viewport::FromInclusive(pEngine->GetDirtyRectInChars()); const auto dirtyAreas = pEngine->GetDirtyArea();
for (const auto dirtyRect : dirtyAreas)
{
auto dirty = Viewport::FromInclusive(dirtyRect);
// Shift the origin of the dirty region to match the underlying buffer so we can // Shift the origin of the dirty region to match the underlying buffer so we can
// compare the two regions directly for intersection. // compare the two regions directly for intersection.
@ -608,6 +612,7 @@ void Renderer::_PaintBufferOutput(_In_ IRenderEngine* const pEngine)
_PaintBufferOutputHelper(pEngine, it, screenLine.Origin(), lineWrapped); _PaintBufferOutputHelper(pEngine, it, screenLine.Origin(), lineWrapped);
} }
} }
}
} }
void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine, void Renderer::_PaintBufferOutputHelper(_In_ IRenderEngine* const pEngine,
@ -834,8 +839,8 @@ void Renderer::_PaintOverlay(IRenderEngine& engine,
// Set it up in a Viewport helper structure and trim it the IME viewport to be within the full console viewport. // Set it up in a Viewport helper structure and trim it the IME viewport to be within the full console viewport.
Viewport viewConv = Viewport::FromInclusive(srCaView); Viewport viewConv = Viewport::FromInclusive(srCaView);
SMALL_RECT srDirty = engine.GetDirtyRectInChars(); for (auto srDirty : engine.GetDirtyArea())
{
// Dirty is an inclusive rectangle, but oddly enough the IME was an exclusive one, so correct it. // Dirty is an inclusive rectangle, but oddly enough the IME was an exclusive one, so correct it.
srDirty.Bottom++; srDirty.Bottom++;
srDirty.Right++; srDirty.Right++;
@ -855,6 +860,7 @@ void Renderer::_PaintOverlay(IRenderEngine& engine,
} }
} }
} }
}
CATCH_LOG(); CATCH_LOG();
} }
@ -890,19 +896,22 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
{ {
try try
{ {
SMALL_RECT srDirty = pEngine->GetDirtyRectInChars(); auto dirtyAreas = pEngine->GetDirtyArea();
Viewport dirtyView = Viewport::FromInclusive(srDirty);
// Get selection rectangles // Get selection rectangles
const auto rectangles = _GetSelectionRects(); const auto rectangles = _GetSelectionRects();
for (auto rect : rectangles) for (auto rect : rectangles)
{ {
for (auto dirtyRect : dirtyAreas)
{
Viewport dirtyView = Viewport::FromInclusive(dirtyRect);
if (dirtyView.TrimToViewport(&rect)) if (dirtyView.TrimToViewport(&rect))
{ {
LOG_IF_FAILED(pEngine->PaintSelection(rect)); LOG_IF_FAILED(pEngine->PaintSelection(rect));
} }
} }
} }
}
CATCH_LOG(); CATCH_LOG();
} }

View file

@ -1686,7 +1686,7 @@ float DxEngine::GetScaling() const noexcept
// - <none> // - <none>
// Return Value: // Return Value:
// - Rectangle describing dirty area in characters. // - Rectangle describing dirty area in characters.
[[nodiscard]] SMALL_RECT DxEngine::GetDirtyRectInChars() noexcept [[nodiscard]] std::vector<SMALL_RECT> DxEngine::GetDirtyArea()
{ {
SMALL_RECT r; SMALL_RECT r;
r.Top = gsl::narrow<SHORT>(floor(_invalidRect.top / _glyphCell.cy)); r.Top = gsl::narrow<SHORT>(floor(_invalidRect.top / _glyphCell.cy));
@ -1698,7 +1698,7 @@ float DxEngine::GetScaling() const noexcept
r.Bottom--; r.Bottom--;
r.Right--; r.Right--;
return r; return { r };
} }
// Routine Description: // Routine Description:

View file

@ -95,7 +95,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
[[nodiscard]] SMALL_RECT GetDirtyRectInChars() noexcept override; [[nodiscard]] std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;

View file

@ -68,7 +68,7 @@ namespace Microsoft::Console::Render
_Out_ FontInfo& Font, _Out_ FontInfo& Font,
const int iDpi) noexcept override; const int iDpi) noexcept override;
SMALL_RECT GetDirtyRectInChars() override; [[nodiscard]] std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;

View file

@ -16,14 +16,14 @@ using namespace Microsoft::Console::Render;
// Return Value: // Return Value:
// - The character dimensions of the current dirty area of the frame. // - The character dimensions of the current dirty area of the frame.
// This is an Inclusive rect. // This is an Inclusive rect.
SMALL_RECT GdiEngine::GetDirtyRectInChars() std::vector<SMALL_RECT> GdiEngine::GetDirtyArea()
{ {
RECT rc = _psInvalidData.rcPaint; RECT rc = _psInvalidData.rcPaint;
SMALL_RECT sr = { 0 }; SMALL_RECT sr = { 0 };
LOG_IF_FAILED(_ScaleByFont(&rc, &sr)); LOG_IF_FAILED(_ScaleByFont(&rc, &sr));
return sr; return { sr };
} }
// Routine Description: // Routine Description:

View file

@ -117,7 +117,7 @@ namespace Microsoft::Console::Render
_Out_ FontInfo& FontInfo, _Out_ FontInfo& FontInfo,
const int iDpi) noexcept = 0; const int iDpi) noexcept = 0;
virtual SMALL_RECT GetDirtyRectInChars() = 0; virtual std::vector<SMALL_RECT> GetDirtyArea() = 0;
[[nodiscard]] virtual HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept = 0; [[nodiscard]] virtual HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept = 0;
[[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept = 0; [[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept = 0;
[[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring& newTitle) noexcept = 0; [[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring& newTitle) noexcept = 0;

View file

@ -403,9 +403,9 @@ UiaEngine::UiaEngine(IUiaEventDispatcher* dispatcher) :
// - <none> // - <none>
// Return Value: // Return Value:
// - Rectangle describing dirty area in characters. // - Rectangle describing dirty area in characters.
[[nodiscard]] SMALL_RECT UiaEngine::GetDirtyRectInChars() noexcept [[nodiscard]] std::vector<SMALL_RECT> UiaEngine::GetDirtyArea()
{ {
return Viewport::Empty().ToInclusive(); return { Viewport::Empty().ToInclusive() };
} }
// Routine Description: // Routine Description:

View file

@ -71,7 +71,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
[[nodiscard]] SMALL_RECT GetDirtyRectInChars() noexcept override; [[nodiscard]] std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;

View file

@ -63,8 +63,19 @@ XtermEngine::XtermEngine(_In_ wil::unique_hfile hPipe,
} }
else else
{ {
const auto dirtyRect = GetDirtyRectInChars(); const auto dirty = GetDirtyArea();
const auto dirtyView = Viewport::FromInclusive(dirtyRect);
// If we have 0 or 1 dirty pieces in the area, set as appropriate.
Viewport dirtyView = dirty.empty() ? Viewport::Empty() : Viewport::FromInclusive(til::at(dirty, 0));
// If there's more than 1, union them all up with the 1 we already have.
for (size_t i = 1; i < dirty.size(); ++i)
{
dirtyView = Viewport::Union(dirtyView, Viewport::FromInclusive(til::at(dirty, i)));
}
// This is expecting the dirty view to be the union of all dirty regions as one big
// rectangle descrbing them all.
if (!_resized && dirtyView == _lastViewport) if (!_resized && dirtyView == _lastViewport)
{ {
// TODO: MSFT:21096414 - This is never actually hit. We set // TODO: MSFT:21096414 - This is never actually hit. We set

View file

@ -17,14 +17,14 @@ using namespace Microsoft::Console::Types;
// Return Value: // Return Value:
// - The character dimensions of the current dirty area of the frame. // - The character dimensions of the current dirty area of the frame.
// This is an Inclusive rect. // This is an Inclusive rect.
SMALL_RECT VtEngine::GetDirtyRectInChars() std::vector<SMALL_RECT> VtEngine::GetDirtyArea()
{ {
SMALL_RECT dirty = _invalidRect.ToInclusive(); SMALL_RECT dirty = _invalidRect.ToInclusive();
if (dirty.Top < _virtualTop) if (dirty.Top < _virtualTop)
{ {
dirty.Top = _virtualTop; dirty.Top = _virtualTop;
} }
return dirty; return { dirty };
} }
// Routine Description: // Routine Description:

View file

@ -89,7 +89,7 @@ namespace Microsoft::Console::Render
_Out_ FontInfo& Font, _Out_ FontInfo& Font,
const int iDpi) noexcept override; const int iDpi) noexcept override;
SMALL_RECT GetDirtyRectInChars() override; std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;

View file

@ -355,7 +355,7 @@ bool WddmConEngine::IsInitialized()
return S_OK; return S_OK;
} }
SMALL_RECT WddmConEngine::GetDirtyRectInChars() std::vector<SMALL_RECT> WddmConEngine::GetDirtyArea()
{ {
SMALL_RECT r; SMALL_RECT r;
r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0; r.Bottom = _displayHeight > 0 ? (SHORT)(_displayHeight - 1) : 0;
@ -363,7 +363,7 @@ SMALL_RECT WddmConEngine::GetDirtyRectInChars()
r.Left = 0; r.Left = 0;
r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0; r.Right = _displayWidth > 0 ? (SHORT)(_displayWidth - 1) : 0;
return r; return { r };
} }
RECT WddmConEngine::GetDisplaySize() RECT WddmConEngine::GetDisplaySize()

View file

@ -61,7 +61,7 @@ namespace Microsoft::Console::Render
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override; [[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
SMALL_RECT GetDirtyRectInChars() override; std::vector<SMALL_RECT> GetDirtyArea() override;
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override; [[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override; [[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;