AtlasEngine: Fix the fix for LRU state after scrolling (#13784)
The absolute disgrace of a fix called 65b71ff
failed to account for `std::move`
being unsafe to use for overlapping ranges. While `std::move` works for trivial
types (it happens to delegate to `memmove`), we need to dynamically switch
between that and `std::move_backward` to be correct.
Without this fix the LRU refresh is incorrect and might lead to crashes.
## Validation Steps Performed
I'm working on a new, pure D2D renderer inside AtlasEngine, which uses
the iterators contained in `_r.cellGlyphMapping` to draw text.
I noticed the bug, because scrolling up caused the text to be garbled
and with this fix applied it works as expected.
This commit is contained in:
parent
64bcc0bd25
commit
c12987af41
|
@ -7,7 +7,6 @@
|
|||
#include <shader_ps.h>
|
||||
#include <shader_vs.h>
|
||||
|
||||
#include "../base/FontCache.h"
|
||||
#include "../../interactivity/win32/CustomWindowMessages.h"
|
||||
|
||||
// #### NOTE ####
|
||||
|
@ -192,42 +191,53 @@ try
|
|||
const auto nothingInvalid = _api.invalidatedRows.x == _api.invalidatedRows.y;
|
||||
const auto offset = static_cast<ptrdiff_t>(_api.scrollOffset) * _api.cellCount.x;
|
||||
auto count = _r.cells.size();
|
||||
ptrdiff_t srcOffset = 0;
|
||||
ptrdiff_t dstOffset = 0;
|
||||
|
||||
if (_api.scrollOffset < 0)
|
||||
{
|
||||
// Scroll up (for instance when new text is being written at the end of the buffer).
|
||||
srcOffset = -offset;
|
||||
dstOffset = 0;
|
||||
count += offset;
|
||||
|
||||
const u16 endRow = _api.cellCount.y + _api.scrollOffset;
|
||||
_api.invalidatedRows.x = nothingInvalid ? endRow : std::min<u16>(_api.invalidatedRows.x, endRow);
|
||||
_api.invalidatedRows.y = _api.cellCount.y;
|
||||
|
||||
// scrollOffset/offset = -1
|
||||
// +----------+ +----------+
|
||||
// | | | xxxxxxxxx| + dst < beg
|
||||
// | xxxxxxxxx| -> |xxxxxxx | + src | < beg - offset
|
||||
// |xxxxxxx | | | | v
|
||||
// +----------+ +----------+ v < end
|
||||
{
|
||||
const auto beg = _r.cells.begin();
|
||||
const auto end = beg + count;
|
||||
std::move(beg - offset, end, beg);
|
||||
}
|
||||
{
|
||||
const auto beg = _r.cellGlyphMapping.begin();
|
||||
const auto end = beg + count;
|
||||
std::move(beg - offset, end, beg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scroll down.
|
||||
srcOffset = 0;
|
||||
dstOffset = offset;
|
||||
count -= offset;
|
||||
|
||||
_api.invalidatedRows.x = 0;
|
||||
_api.invalidatedRows.y = nothingInvalid ? _api.scrollOffset : std::max<u16>(_api.invalidatedRows.y, _api.scrollOffset);
|
||||
}
|
||||
|
||||
// scrollOffset/offset = 1
|
||||
// +----------+ +----------+
|
||||
// | xxxxxxxxx| | | + src < beg
|
||||
// |xxxxxxx | -> | xxxxxxxxx| | ^
|
||||
// | | |xxxxxxx | v | < end - offset
|
||||
// +----------+ +----------+ + dst < end
|
||||
{
|
||||
const auto beg = _r.cells.begin();
|
||||
const auto src = beg + srcOffset;
|
||||
const auto dst = beg + dstOffset;
|
||||
std::move(src, src + count, dst);
|
||||
const auto end = beg + count;
|
||||
std::move_backward(beg, end - offset, end);
|
||||
}
|
||||
{
|
||||
const auto beg = _r.cellGlyphMapping.begin();
|
||||
const auto src = beg + srcOffset;
|
||||
const auto dst = beg + dstOffset;
|
||||
std::move(src, src + count, dst);
|
||||
const auto end = beg + count;
|
||||
std::move_backward(beg, end - offset, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue