Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render row-by-row instead of invalidating entire screen #5185

Merged
30 commits merged into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7e8f039
Start moving dx renderer onto bitmap.
miniksa Mar 23, 2020
b46b5d0
it works!
miniksa Mar 23, 2020
78c1bc1
try to get present1 working and get mad because std::vector<bool> is …
miniksa Mar 23, 2020
39d67e3
Merge branch 'master' into dev/miniksa/dx_bitmap
miniksa Mar 30, 2020
777524a
Change invalidation to full rows to restore ligature drawing.
miniksa Mar 30, 2020
a15af9b
Add tests for til and round out the operators.
miniksa Mar 30, 2020
ac01c0b
code format
miniksa Mar 30, 2020
c478983
code format and audit mode.
miniksa Mar 31, 2020
f39b352
Dustin's suggestion about helper for invalidating rectangles .
miniksa Apr 1, 2020
0d863c2
Fix selection issues.
miniksa Apr 1, 2020
ea8e379
Restore scrolling by appropriately scaling dirty rectangles from cell…
miniksa Apr 1, 2020
1d72e6b
Don't redraw everything. We're competent enough at scrolling in the D…
miniksa Apr 1, 2020
1d51d86
Report the delta when scroll buffer circles as there is no implicit v…
miniksa Apr 3, 2020
b8c66dd
Invalidate all with retro terminal effects experimental feature turne…
miniksa Apr 3, 2020
1e5e4eb
Don't use incremental drawing parameters on the first frame. Just use…
miniksa Apr 3, 2020
46e526c
Add compensation for High DPI. Not perfect but way better.
miniksa Apr 6, 2020
f11c7a1
Remove unused constructor in float. Add scale tests to Rectangle (rem…
miniksa Apr 8, 2020
162b516
Tests for rectangle constructors from floats + code formatting pass.
miniksa Apr 8, 2020
45f8144
change to constexpr
miniksa Apr 8, 2020
351dc9c
GetClient for composition now uses size scale factor directly (and I …
miniksa Apr 8, 2020
d42f609
Adjust the present1/present logic so it will retry if present1 fails …
miniksa Apr 10, 2020
3e060e6
Literally clear everything, including the gutters, when the complete …
miniksa Apr 10, 2020
4eddc8d
Fix selection invalidation issues. This was always broken but the nat…
miniksa Apr 10, 2020
f22577d
Fix issue with algorithm around re-using known previous viewport as r…
miniksa Apr 10, 2020
f4b39ec
code format
miniksa Apr 10, 2020
8abf479
Use GDI Classic measuring mode to eliminate blended half-pixels at th…
miniksa Apr 10, 2020
d0e6dd1
separate concerns between updating viewport and scrolling.
miniksa Apr 10, 2020
b06720a
Disable incremental for High DPI as it doesn't work with the implicit…
miniksa Apr 10, 2020
1207e80
Put natural rendering back.
miniksa Apr 10, 2020
24ecd5b
Actually lock in selection code so it doesn't pull the rug out from u…
miniksa Apr 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

if (point.Properties().IsLeftButtonPressed())
{
auto lock = _terminal->LockForWriting();

const auto cursorPosition = point.Position();
const auto terminalPosition = _GetTerminalPosition(cursorPosition);

Expand Down Expand Up @@ -978,6 +980,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_lastMouseClickTimestamp = point.Timestamp();
_lastMouseClickPos = cursorPosition;
}

_renderer->TriggerSelection();
}
else if (point.Properties().IsRightButtonPressed())
Expand Down Expand Up @@ -1036,6 +1039,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation

if (point.Properties().IsLeftButtonPressed())
{
auto lock = _terminal->LockForWriting();

const auto cursorPosition = point.Position();

if (_singleClickTouchdownPos)
Expand Down
15 changes: 13 additions & 2 deletions src/cascadia/TerminalCore/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,20 +701,31 @@ void Terminal::_AdjustCursorPosition(const COORD proposedPosition)

if (notifyScroll)
{
_buffer->GetRenderTarget().TriggerRedrawAll();
// We have to report the delta here because we might have circled the text buffer.
// That didn't change the viewport and therefore the TriggerScroll(void)
// method can't detect the delta on its own.
COORD delta{ 0, -gsl::narrow<SHORT>(newRows) };
_buffer->GetRenderTarget().TriggerScroll(&delta);
_NotifyScrollEvent();
}
}

void Terminal::UserScrollViewport(const int viewTop)
{
// we're going to modify state here that the renderer could be reading.
auto lock = LockForWriting();

const auto clampedNewTop = std::max(0, viewTop);
const auto realTop = ViewStartIndex();
const auto newDelta = realTop - clampedNewTop;
// if viewTop > realTop, we want the offset to be 0.

_scrollOffset = std::max(0, newDelta);
_buffer->GetRenderTarget().TriggerRedrawAll();

// We can use the void variant of TriggerScroll here because
// we adjusted the viewport so it can detect the difference
// from the previous frame drawn.
_buffer->GetRenderTarget().TriggerScroll();
}

int Terminal::GetScrollOffset() noexcept
Expand Down
2 changes: 1 addition & 1 deletion src/inc/til.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "til/some.h"
#include "til/size.h"
#include "til/point.h"
#include "til/rectangle.h"
#include "til/operators.h"
#include "til/rectangle.h"
miniksa marked this conversation as resolved.
Show resolved Hide resolved
#include "til/bitmap.h"
#include "til/u8u16convert.h"

Expand Down
11 changes: 8 additions & 3 deletions src/inc/til/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
THROW_HR_IF(E_INVALIDARG, !_rc.contains(pt));
_runs.reset(); // reset cached runs on any non-const method

til::at(_bits, _rc.index_of(pt)) = true;
_bits.set(_rc.index_of(pt));

_dirty |= til::rectangle{ pt };
}
Expand All @@ -283,9 +283,9 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
THROW_HR_IF(E_INVALIDARG, !_rc.contains(rc));
_runs.reset(); // reset cached runs on any non-const method

for (const auto pt : rc)
for (auto row = rc.top(); row < rc.bottom(); ++row)
{
til::at(_bits, _rc.index_of(pt)) = true;
_bits.set(_rc.index_of(til::point{ rc.left(), row }), rc.width(), true);
}

_dirty |= rc;
Expand Down Expand Up @@ -378,6 +378,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return _dirty == _rc;
}

constexpr til::size size() const noexcept
miniksa marked this conversation as resolved.
Show resolved Hide resolved
{
return _sz;
}

std::wstring to_string() const
{
std::wstringstream wss;
Expand Down
4 changes: 0 additions & 4 deletions src/inc/til/operators.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

#pragma once

#include "rectangle.h"
#include "size.h"
#include "bitmap.h"

namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
// Operators go here when they involve two headers that can't/don't include each other.
Expand Down
13 changes: 13 additions & 0 deletions src/inc/til/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return *this;
}

template<typename TilMath>
point scale(TilMath, const float scale) const
{
struct
{
float x, y;
} pt;
THROW_HR_IF(E_ABORT, !base::CheckMul(scale, _x).AssignIfValid(&pt.x));
THROW_HR_IF(E_ABORT, !base::CheckMul(scale, _y).AssignIfValid(&pt.y));

return til::point(TilMath(), pt);
}

point operator/(const point& other) const
{
ptrdiff_t x;
Expand Down
52 changes: 48 additions & 4 deletions src/inc/til/rectangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@

#pragma once

#include "point.h"
#include "size.h"
#include "some.h"

#ifdef UNIT_TESTING
class RectangleTests;
#endif
Expand Down Expand Up @@ -179,6 +175,22 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
}

// This template will convert to rectangle from anything that has a Left, Top, Right, and Bottom field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>
constexpr rectangle(TilMath, const TOther& other, std::enable_if_t<std::is_floating_point_v<decltype(std::declval<TOther>().Left)> && std::is_floating_point_v<decltype(std::declval<TOther>().Top)> && std::is_floating_point_v<decltype(std::declval<TOther>().Right)> && std::is_floating_point_v<decltype(std::declval<TOther>().Bottom)>, int> /*sentinel*/ = 0) :
miniksa marked this conversation as resolved.
Show resolved Hide resolved
rectangle(til::point{ TilMath::template cast<ptrdiff_t>(other.Left), TilMath::template cast<ptrdiff_t>(other.Top) }, til::point{ TilMath::template cast<ptrdiff_t>(other.Right), TilMath::template cast<ptrdiff_t>(other.Bottom) })
{
}

// This template will convert to rectangle from anything that has a left, top, right, and bottom field that are floating-point;
// a math type is required.
template<typename TilMath, typename TOther>
constexpr rectangle(TilMath, const TOther& other, std::enable_if_t<std::is_floating_point_v<decltype(std::declval<TOther>().left)> && std::is_floating_point_v<decltype(std::declval<TOther>().top)> && std::is_floating_point_v<decltype(std::declval<TOther>().right)> && std::is_floating_point_v<decltype(std::declval<TOther>().bottom)>, int> /*sentinel*/ = 0) :
rectangle(til::point{ TilMath::template cast<ptrdiff_t>(other.left), TilMath::template cast<ptrdiff_t>(other.top) }, til::point{ TilMath::template cast<ptrdiff_t>(other.right), TilMath::template cast<ptrdiff_t>(other.bottom) })
{
}

constexpr bool operator==(const rectangle& other) const noexcept
{
return _topLeft == other._topLeft &&
Expand Down Expand Up @@ -636,6 +648,38 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return *this;
}

// scale_up will scale the entire rectangle up by the size factor
// This includes moving the origin.
rectangle scale_up(const size& size) const
{
const auto topLeft = _topLeft * size;
miniksa marked this conversation as resolved.
Show resolved Hide resolved
const auto bottomRight = _bottomRight * size;
return til::rectangle{ topLeft, bottomRight };
}
miniksa marked this conversation as resolved.
Show resolved Hide resolved

// scale_down will scale the entire rectangle down by the size factor,
// but rounds the bottom-right corner out.
// This includes moving the origin.
rectangle scale_down(const size& size) const
{
auto topLeft = _topLeft;
auto bottomRight = _bottomRight;
topLeft = topLeft / size;
miniksa marked this conversation as resolved.
Show resolved Hide resolved

// Move bottom right point into a size
// Use size specialization of divide_ceil to round up against the size given.
// Add leading addition to point to convert it back into a point.
bottomRight = til::point{} + til::size{ right(), bottom() }.divide_ceil(size);

return til::rectangle{ topLeft, bottomRight };
}

template<typename TilMath>
rectangle scale(TilMath, const float scale) const
{
return til::rectangle{ _topLeft.scale(TilMath{}, scale), _bottomRight.scale(TilMath{}, scale) };
}

#pragma endregion

constexpr ptrdiff_t top() const noexcept
Expand Down
13 changes: 13 additions & 0 deletions src/inc/til/size.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return size{ width, height };
}

template<typename TilMath>
size scale(TilMath, const float scale) const
{
struct
{
float Width, Height;
} sz;
THROW_HR_IF(E_ABORT, !base::CheckMul(scale, _width).AssignIfValid(&sz.Width));
THROW_HR_IF(E_ABORT, !base::CheckMul(scale, _height).AssignIfValid(&sz.Height));

return til::size(TilMath(), sz);
}

size operator/(const size& other) const
{
ptrdiff_t width;
Expand Down
75 changes: 68 additions & 7 deletions src/renderer/base/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,22 @@ void Renderer::TriggerSelection()
// Get selection rectangles
const auto rects = _GetSelectionRects();

// Restrict all previous selection rectangles to inside the current viewport bounds
for (auto& sr : _previousSelection)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be sure, sr here is viewport relative, or buffer-relative?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be relative to the visible viewport.

{
// Make the exclusive SMALL_RECT into a til::rectangle.
til::rectangle rc{ Viewport::FromExclusive(sr).ToInclusive() };

// Make a viewport representing the coordinates that are currently presentable.
const til::rectangle viewport{ til::size{ _pData->GetViewport().Dimensions() } };

// Intersect them so we only invalidate things that are still visible.
rc &= viewport;

// Convert back into the exclusive SMALL_RECT and store in the vector.
sr = Viewport::FromInclusive(rc).ToExclusive();
}

std::for_each(_rgpEngines.begin(), _rgpEngines.end(), [&](IRenderEngine* const pEngine) {
LOG_IF_FAILED(pEngine->InvalidateSelection(_previousSelection));
LOG_IF_FAILED(pEngine->InvalidateSelection(rects));
Expand Down Expand Up @@ -330,13 +346,26 @@ bool Renderer::_CheckViewportAndScroll()
coordDelta.X = srOldViewport.Left - srNewViewport.Left;
coordDelta.Y = srOldViewport.Top - srNewViewport.Top;

std::for_each(_rgpEngines.begin(), _rgpEngines.end(), [&](IRenderEngine* const pEngine) {
LOG_IF_FAILED(pEngine->UpdateViewport(srNewViewport));
LOG_IF_FAILED(pEngine->InvalidateScroll(&coordDelta));
});
for (auto engine : _rgpEngines)
{
LOG_IF_FAILED(engine->UpdateViewport(srNewViewport));
}

_srViewportPrevious = srNewViewport;

return coordDelta.X != 0 || coordDelta.Y != 0;
if (coordDelta.X != 0 || coordDelta.Y != 0)
{
for (auto engine : _rgpEngines)
{
LOG_IF_FAILED(engine->InvalidateScroll(&coordDelta));
}

_ScrollPreviousSelection(coordDelta);

return true;
}

return false;
}

// Routine Description:
Expand Down Expand Up @@ -369,6 +398,8 @@ void Renderer::TriggerScroll(const COORD* const pcoordDelta)
LOG_IF_FAILED(pEngine->InvalidateScroll(pcoordDelta));
});

_ScrollPreviousSelection(*pcoordDelta);

_NotifyPaintFrame();
}

Expand Down Expand Up @@ -927,10 +958,13 @@ void Renderer::_PaintSelection(_In_ IRenderEngine* const pEngine)
{
for (auto dirtyRect : dirtyAreas)
{
// Make a copy as `TrimToViewport` will manipulate it and
// can destroy it for the next dirtyRect to test against.
auto rectCopy = rect;
Viewport dirtyView = Viewport::FromInclusive(dirtyRect);
if (dirtyView.TrimToViewport(&rect))
if (dirtyView.TrimToViewport(&rectCopy))
{
LOG_IF_FAILED(pEngine->PaintSelection(rect));
LOG_IF_FAILED(pEngine->PaintSelection(rectCopy));
}
}
}
Expand Down Expand Up @@ -1002,6 +1036,33 @@ std::vector<SMALL_RECT> Renderer::_GetSelectionRects() const
return result;
}

// Method Description:
// - Offsets all of the selection rectangles we might be holding onto
// as the previously selected area. If the whole viewport scrolls,
// we need to scroll these areas also to ensure they're invalidated
// properly when the selection further changes.
// Arguments:
// - delta - The scroll delta
// Return Value:
// - <none> - Updates internal state instead.
void Renderer::_ScrollPreviousSelection(const til::point delta)
{
if (delta != til::point{ 0, 0 })
{
for (auto& sr : _previousSelection)
{
// Get a rectangle representing this piece of the selection.
til::rectangle rc = Viewport::FromExclusive(sr).ToInclusive();

// Offset the entire existing rectangle by the delta.
rc += delta;

// Store it back into the vector.
sr = Viewport::FromInclusive(rc).ToExclusive();
}
}
}

// Method Description:
// - Adds another Render engine to this renderer. Future rendering calls will
// also be sent to the new renderer.
Expand Down
1 change: 1 addition & 0 deletions src/renderer/base/renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ namespace Microsoft::Console::Render
SMALL_RECT _srViewportPrevious;

std::vector<SMALL_RECT> _GetSelectionRects() const;
void _ScrollPreviousSelection(const til::point delta);
std::vector<SMALL_RECT> _previousSelection;

[[nodiscard]] HRESULT _PaintTitle(IRenderEngine* const pEngine);
Expand Down
Loading