Repository: microsoft/terminal
File: src/terminal/adapter/SixelParser.cpp (C++)

Code before:
        }
        sixelValue >>= 1;
    }
    _imageCursor.x += repeatCount;
}

void SixelParser::_eraseImageBufferRows(const int rowCount, const til::CoordType rowOffset) noexcept
{
    const auto pixelCount = rowCount * _cellSize.height;
    const auto bufferOffset = rowOffset * _cellSize.height * _imageMaxWidth;
    const auto bufferOffsetEnd = bufferOffset + pixelCount * _imageMaxWidth;
    if (static_cast<size_t>(bufferOffsetEnd) >= _imageBuffer.size()) [[unlikely]]
    {
        _decreaseFilledBackgroundHeight(_imageCursor.y);
        _imageBuffer.clear();
        _imageCursor.y = 0;
    }
    else
    {
        _decreaseFilledBackgroundHeight(pixelCount);
        _imageBuffer.erase(_imageBuffer.begin() + bufferOffset, _imageBuffer.begin() + bufferOffsetEnd);
        _imageCursor.y -= pixelCount;
    }
}

void SixelParser::_maybeFlushImageBuffer(const bool endOfSequence)
{
    // Regardless of whether we flush the image or not, we always calculate how
    // much we need to scroll in advance. This algorithm is a bit odd. If there
    // isn't enough space for the current segment, it'll scroll until it can fit
    // the segment with a pixel to spare. So in the case that it's an exact fit,
    // it's expected that we'd scroll an additional line. Although this is not
    // common, since it only occurs for pixel aspect ratios of 4:1 or more. Also
    // note that we never scroll more than the margin height, since that would
    // result in the top of the segment being pushed offscreen.
    if (_segmentHeight > _availablePixelHeight && !_displayMode) [[unlikely]]
    {
        const auto marginPixelHeight = _textMargins.height() * _cellSize.height;
        while (_availablePixelHeight < marginPixelHeight && _segmentHeight >= _availablePixelHeight)
        {
            _pendingTextScrollCount += 1;
            _availablePixelHeight += _cellSize.height;
        }
    }

    // Once we've calculated how much scrolling was necessary for the existing
    // segment height, we don't need to track that any longer. The next segment
    // will start with the active sixel height.
    _segmentHeight = _sixelHeight;

    // This method is called after every newline (DECGNL), but we don't want to

Review comment (suggestion):
I added some comments, but the idea here is that `pixelValue` is highly random leading to branch mispredictions when bit-testing it. We can avoid that by always loading the old bitmap value and then CMOVing between the old and new value before storing it again. With modern CPUs and their deep pipelines this runs faster.

Code after:
    static_assert(alignof(IndexedPixel) == alignof(int16_t));

    // Then we need to render the 6 vertical pixels that are represented by the
    // bits in the sixel value. Although note that each of these sixel pixels
    // may cover more than one device pixel, depending on the aspect ratio.
    const auto targetOffset = _imageCursor.y * _imageMaxWidth + _imageCursor.x;
    const auto foreground = std::bit_cast<int16_t>(_foregroundPixel);
    auto imageBufferPtr = reinterpret_cast<int16_t*>(_imageBuffer.data() + targetOffset);

    // A aspect ratio of 1:1 is the most common and worth optimizing.
    if (_pixelAspectRatio == 1)
    {
        do
        {
            // This gets unrolled by MSVC. It's written this way to use CMOV instructions.
            // Modern CPUs have fat caches and deep pipelines. It's better to do pointless reads
            // from memory than causing branch misprediction, as sixelValue is highly random.
            for (int i = 0; i < 6; i++)
            {
                const auto test = sixelValue & (1 << i);
                // Possibly pointless read from memory, but...
                const auto before = imageBufferPtr[i * _imageMaxWidth];
                // ...it allows the compiler to turn this into a CMOV (= no branch misprediction).
                const auto after = test ? foreground : before;
                imageBufferPtr[i * _imageMaxWidth] = after;
            }

            _imageCursor.x += 1;
            imageBufferPtr += 1;
            repeatCount -= 1;
        } while (repeatCount > 0);
    }
    else
    {
        for (auto i = 0; i < 6; i++)
        {
            if (sixelValue & 1)
            {
                auto repeatAspectRatio = _pixelAspectRatio;
                do
                {
                    // If this used std::fill_n or just a primitive loop, MSVC would compile
                    // it to a `rep stosw` instruction, which has a high startup cost.
                    // This is not ideal when our repeatCount is almost always small.
                    // The way this does ptr++ and len-- is also ideal for optimization.
                    auto ptr = imageBufferPtr;
                    auto remaining = repeatCount;
                    do
                    {
                        __iso_volatile_store16(ptr++, foreground);
                    } while (--remaining != 0);