910e62b5创建于 1月15日历史提交
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gpu/command_buffer/client/mock_transfer_buffer.h"

#include "base/bits.h"
#include "base/compiler_specific.h"
#include "gpu/command_buffer/common/command_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace gpu {

MockTransferBuffer::MockTransferBuffer(CommandBuffer* command_buffer,
                                       unsigned int size,
                                       unsigned int result_size,
                                       unsigned int alignment,
                                       bool initialize_fail)
    : command_buffer_(command_buffer),
      size_(size),
      result_size_(result_size),
      alignment_(alignment),
      actual_buffer_index_(0),
      expected_buffer_index_(0),
      expected_offset_(result_size),
      actual_offset_(result_size),
      initialize_fail_(initialize_fail) {
  // We have to allocate the buffers here because
  // we need to know their address before
  // {Raster,GLES2}Implementation::Initialize is called.
  for (int ii = 0; ii < kNumBuffers; ++ii) {
    buffers_[ii] = command_buffer_->CreateTransferBuffer(
        size_ + ii * alignment_, &buffer_ids_[ii]);
    EXPECT_NE(-1, buffer_ids_[ii]);
  }
}

MockTransferBuffer::~MockTransferBuffer() = default;

base::UnguessableToken MockTransferBuffer::shared_memory_guid() const {
  return base::UnguessableToken();
}

bool MockTransferBuffer::Initialize(unsigned int starting_buffer_size,
                                    unsigned int result_size,
                                    unsigned int /* min_buffer_size */,
                                    unsigned int /* max_buffer_size */,
                                    unsigned int alignment) {
  // Just check they match.
  return size_ == starting_buffer_size && result_size_ == result_size &&
         alignment_ == alignment && !initialize_fail_;
}

int MockTransferBuffer::GetShmId() {
  return buffer_ids_[actual_buffer_index_];
}

void* MockTransferBuffer::AcquireResultBuffer() {
  EXPECT_FALSE(outstanding_result_pointer_);
  outstanding_result_pointer_ = true;
  return UNSAFE_TODO(actual_buffer() + actual_buffer_index_ * alignment_);
}

void MockTransferBuffer::ReleaseResultBuffer() {
  EXPECT_TRUE(outstanding_result_pointer_);
  outstanding_result_pointer_ = false;
}

int MockTransferBuffer::GetResultOffset() {
  return actual_buffer_index_ * alignment_;
}

void MockTransferBuffer::Free() {
  NOTREACHED();
}

bool MockTransferBuffer::HaveBuffer() const {
  return true;
}

base::span<uint8_t> MockTransferBuffer::AllocUpTo(unsigned int size) {
  EXPECT_TRUE(last_alloc_.empty());

  // Toggle which buffer we get each time to simulate the buffer being
  // reallocated.
  actual_buffer_index_ = (actual_buffer_index_ + 1) % kNumBuffers;

  size = std::min(size, MaxTransferBufferSize());
  if (actual_offset_ + size > size_) {
    actual_offset_ = result_size_;
  }
  uint32_t offset = actual_offset_;
  actual_offset_ += RoundToAlignment(size);

  // Make sure each buffer has a different offset.
  last_alloc_ =
      actual_span().subspan(offset + actual_buffer_index_ * alignment_, size);
  return last_alloc_;
}

base::span<uint8_t> MockTransferBuffer::Alloc(unsigned int size) {
  EXPECT_LE(size, MaxTransferBufferSize());
  base::span<uint8_t> span = AllocUpTo(size);
  EXPECT_EQ(span.size(), size);
  return span;
}

RingBuffer::Offset MockTransferBuffer::GetOffset(void* pointer) const {
  // Make sure each buffer has a different offset.
  return static_cast<uint8_t*>(pointer) - actual_buffer();
}

void MockTransferBuffer::DiscardBlock(void* p) {
  EXPECT_EQ(last_alloc_.data(), static_cast<uint8_t*>(p));
  last_alloc_ = {};
}

void MockTransferBuffer::FreePendingToken(void* p, unsigned int /* token */) {
  EXPECT_EQ(last_alloc_.data(), static_cast<uint8_t*>(p));
  last_alloc_ = {};
}

unsigned int MockTransferBuffer::GetSize() const {
  return 0;
}

unsigned int MockTransferBuffer::GetFreeSize() const {
  return 0;
}

unsigned int MockTransferBuffer::GetFragmentedFreeSize() const {
  return 0;
}

unsigned int MockTransferBuffer::GetMaxSize() const {
  return 0;
}

void MockTransferBuffer::ShrinkLastBlock(unsigned int new_size) {}

uint32_t MockTransferBuffer::MaxTransferBufferSize() {
  return size_ - result_size_;
}

unsigned int MockTransferBuffer::RoundToAlignment(unsigned int size) {
  return base::bits::AlignUp(size, alignment_);
}

bool MockTransferBuffer::InSync() {
  return expected_buffer_index_ == actual_buffer_index_ &&
         expected_offset_ == actual_offset_;
}

MockTransferBuffer::ExpectedMemoryInfo MockTransferBuffer::GetExpectedMemory(
    uint32_t size) {
  ExpectedMemoryInfo mem;
  mem.offset = AllocateExpectedTransferBuffer(size);
  mem.id = GetExpectedTransferBufferId();
  mem.ptr = static_cast<uint8_t*>(
      GetExpectedTransferAddressFromOffset(mem.offset, size));
  mem.span = expected_span().subspan(mem.offset);
  return mem;
}

MockTransferBuffer::ExpectedMemoryInfo
MockTransferBuffer::GetExpectedResultMemory(uint32_t size) {
  ExpectedMemoryInfo mem;
  mem.offset = GetExpectedResultBufferOffset();
  mem.id = GetExpectedResultBufferId();
  mem.ptr = static_cast<uint8_t*>(
      GetExpectedTransferAddressFromOffset(mem.offset, size));
  mem.span = expected_span().subspan(mem.offset);
  return mem;
}

uint32_t MockTransferBuffer::AllocateExpectedTransferBuffer(uint32_t size) {
  EXPECT_LE(size, MaxTransferBufferSize());

  // Toggle which buffer we get each time to simulate the buffer being
  // reallocated.
  expected_buffer_index_ = (expected_buffer_index_ + 1) % kNumBuffers;

  if (expected_offset_ + size > size_) {
    expected_offset_ = result_size_;
  }
  uint32_t offset = expected_offset_;
  expected_offset_ += RoundToAlignment(size);

  // Make sure each buffer has a different offset.
  return offset + expected_buffer_index_ * alignment_;
}

void* MockTransferBuffer::GetExpectedTransferAddressFromOffset(uint32_t offset,
                                                               uint32_t size) {
  EXPECT_GE(offset, expected_buffer_index_ * alignment_);
  EXPECT_LE(offset + size, size_ + expected_buffer_index_ * alignment_);
  return UNSAFE_TODO(expected_buffer() + offset);
}

int MockTransferBuffer::GetExpectedResultBufferId() {
  return buffer_ids_[expected_buffer_index_];
}

uint32_t MockTransferBuffer::GetExpectedResultBufferOffset() {
  return expected_buffer_index_ * alignment_;
}

int MockTransferBuffer::GetExpectedTransferBufferId() {
  return buffer_ids_[expected_buffer_index_];
}

}  // namespace gpu