<commit_before>//
// PROJECT:         Aspia Remote Desktop
// FILE:            desktop_capture/differ.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     <NAME> (<EMAIL>)
//

#include "desktop_capture/differ.h"

#include "desktop_capture/diff_block_sse2.h"

namespace aspia {

static const int kBytesPerPixel = 4;
static const int kBlockSize = 16;
static const int kBytesPerBlock = kBytesPerPixel * kBlockSize;

static INLINE uint8_t DiffFullBlock_C(const uint8_t* image1,
                                      const uint8_t* image2,
                                      int bytes_per_row)
{
    for (int y = 0; y < kBlockSize; ++y)
    {
        if (memcmp(image1, image2, kBytesPerBlock) != 0)
        {
            return 1U;
        }

        image1 += bytes_per_row;
        image2 += bytes_per_row;
    }

    return 0U;
}

//
// Check for diffs in upper-left portion of the block. The size of the portion
// to check is specified by the |width| and |height| values.
// Note that if we force the capturer to always return images whose width and
// height are multiples of kBlockSize, then this will never be called.
//
static INLINE uint8_t DiffPartialBlock(const uint8_t* prev_image,
                                       const uint8_t* curr_image,
                                       int bytes_per_row,
                                       int bytes_per_block,
                                       int height)
{
    for (int y = 0; y < height; ++y)
    {
        if (memcmp(prev_image, curr_image, bytes_per_block) != 0)
        {
            return 1U;
        }

        prev_image += bytes_per_row;
        curr_image += bytes_per_row;
    }

    return 0U;
}

Differ::Differ(const DesktopSize& size)
    : size_(size),
      bytes_per_row_(size.Width() * kBytesPerPixel),
      diff_width_(((size.Width() + kBlockSize - 1) / kBlockSize) + 1),
      diff_height_(((size.Height() + kBlockSize - 1) / kBlockSize) + 1),
      full_blocks_x_(size.Width() / kBlockSize),
      full_blocks_y_(size.Height() / kBlockSize)
{
    const int diff_info_size = diff_width_ * diff_height_;

    diff_info_ = std::make_unique<uint8_t[]>(diff_info_size);
    memset(diff_info_.get(), 0, diff_info_size);

    // Calc size of partial blocks which may be present on right and bottom
    // edge.
    partial_column_width_ = size.Width() - (full_blocks_x_ * kBlockSize);
    partial_row_height_ = size.Height() - (full_blocks_y_ * kBlockSize);

    // Offset from the start of one block-row to the next.
    block_stride_y_ = bytes_per_row_ * kBlockSize;
}

//
// Identify all of the blocks that contain changed pixels.
//
void Differ::MarkDirtyBlocks(const uint8_t* prev_image, const uint8_t* curr_image)
{
    const uint8_t* prev_block_row_start = prev_image;
    const uint8_t* curr_block_row_start = curr_image;

    // Offset from the start of one diff_info row to the next.
    const int diff_stride = diff_width_;

    uint8_t* is_diff_row_start = diff_info_.get();

    for (int y = 0; y < full_blocks_y_; ++y)
    {
        const uint8_t* prev_block = prev_block_row_start;
        const uint8_t* curr_block = curr_block_row_start;

        uint8_t* is_different = is_diff_row_start;

        for (int x = 0; x < full_blocks_x_; ++x)
        {
            // For x86 and x86_64, we do not support processors that do not
            // have SSE2 instructions support.
            if (kBlockSize == 16)
            {
                // Mark this block as being modified so that it gets
                // incorporated into a dirty rect.
                *is_different = DiffFullBlock_16x16_SSE2(prev_block,
                                                         curr_block,
                                                         bytes_per_row_);
            }
            else if (kBlockSize == 32)
            {
                // Mark this block as being modified so that it gets
                // incorporated into a dirty rect.
                *is_different = DiffFullBlock_32x32_SSE2(prev_block,
                                                         curr_block,
                                                         bytes_per_row_);
            }

            prev_block += kBytesPerBlock;
            curr_block += kBytesPerBlock;

            ++is_different;
        }

        //
        // If there is a partial column at the end, handle it.
        // This condition should rarely, if ever, occur.
        //
        if (partial_column_width_ != 0)
        {
            *is_different = DiffPartialBlock(prev_block,
                                             curr_block,
                                             bytes_per_row_,
                                             kBytesPerBlock,
                                             kBlockSize);

            ++is_different;
        }
<commit_msg>- Remove unneeded increment<commit_after>//
// PROJECT:         Aspia Remote Desktop
// FILE:            desktop_capture/differ.cc
// LICENSE:         Mozilla Public License Version 2.0
// PROGRAMMERS:     <NAME> (<EMAIL>)
//

#include "desktop_capture/differ.h"

#include "desktop_capture/diff_block_sse2.h"

namespace aspia {

static const int kBytesPerPixel = 4;
static const int kBlockSize = 16;
static const int kBytesPerBlock = kBytesPerPixel * kBlockSize;

static INLINE uint8_t DiffFullBlock_C(const uint8_t* image1,
                                      const uint8_t* image2,
                                      int bytes_per_row)
{
    for (int y = 0; y < kBlockSize; ++y)
    {
        if (memcmp(image1, image2, kBytesPerBlock) != 0)
        {
            return 1U;
        }

        image1 += bytes_per_row;
        image2 += bytes_per_row;
    }

    return 0U;
}

//
// Check for diffs in upper-left portion of the block. The size of the portion
// to check is specified by the |width| and |height| values.
// Note that if we force the capturer to always return images whose width and
// height are multiples of kBlockSize, then this will never be called.
//
static INLINE uint8_t DiffPartialBlock(const uint8_t* prev_image,
                                       const uint8_t* curr_image,
                                       int bytes_per_row,
                                       int bytes_per_block,
                                       int height)
{
    for (int y = 0; y < height; ++y)
    {
        if (memcmp(prev_image, curr_image, bytes_per_block) != 0)
        {
            return 1U;
        }

        prev_image += bytes_per_row;
        curr_image += bytes_per_row;
    }

    return 0U;
}

Differ::Differ(const DesktopSize& size)
    : size_(size),
      bytes_per_row_(size.Width() * kBytesPerPixel),
      diff_width_(((size.Width() + kBlockSize - 1) / kBlockSize) + 1),
      diff_height_(((size.Height() + kBlockSize - 1) / kBlockSize) + 1),
      full_blocks_x_(size.Width() / kBlockSize),
      full_blocks_y_(size.Height() / kBlockSize)
{
    const int diff_info_size = diff_width_ * diff_height_;

    diff_info_ = std::make_unique<uint8_t[]>(diff_info_size);
    memset(diff_info_.get(), 0, diff_info_size);

    // Calc size of partial blocks which may be present on right and bottom
    // edge.
    partial_column_width_ = size.Width() - (full_blocks_x_ * kBlockSize);
    partial_row_height_ = size.Height() - (full_blocks_y_ * kBlockSize);

    // Offset from the start of one block-row to the next.
    block_stride_y_ = bytes_per_row_ * kBlockSize;
}

//
// Identify all of the blocks that contain changed pixels.
//
void Differ::MarkDirtyBlocks(const uint8_t* prev_image, const uint8_t* curr_image)
{
    const uint8_t* prev_block_row_start = prev_image;
    const uint8_t* curr_block_row_start = curr_image;

    // Offset from the start of one diff_info row to the next.
    const int diff_stride = diff_width_;

    uint8_t* is_diff_row_start = diff_info_.get();

    for (int y = 0; y < full_blocks_y_; ++y)
    {
        const uint8_t* prev_block = prev_block_row_start;
        const uint8_t* curr_block = curr_block_row_start;

        uint8_t* is_different = is_diff_row_start;

        for (int x = 0; x < full_blocks_x_; ++x)
        {
            // For x86 and x86_64, we do not support processors that do not
            // have SSE2 instructions support.
            if (kBlockSize == 16)
            {
                // Mark this block as being modified so that it gets
                // incorporated into a dirty rect.
                *is_different = DiffFullBlock_16x16_SSE2(prev_block,
                                                         curr_block,
                                                         bytes_per_row_);
            }
            else if (kBlockSize == 32)
            {
                // Mark this block as being modified so that it gets
                // incorporated into a dirty rect.
                *is_different = DiffFullBlock_32x32_SSE2(prev_block,
                                                         curr_block,
                                                         bytes_per_row_);
            }

            prev_block += kBytesPerBlock;
            curr_block += kBytesPerBlock;

            ++is_different;
        }

        // If there is a partial column at the end, handle it.
        // This condition should rarely, if ever, occur.
        if (partial_column_width_ != 0)
        {
            *is_different = DiffPartialBlock(prev_block,
                                             curr_block,
                                             bytes_per_row_,
                                             kBytesPerBlock,
                                             kBlockSize);
        }

{'fraction_non_alphanumeric': 0.08057018903005887, 'fraction_numerical': 0.013221774610060945, 'mean_word_length': 1.611815484219045, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 52, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6624365', 'n_tokens_mistral': 2865, 'n_tokens_neox': 2736, 'n_words': 760}