blob: 49f29f38409ad23a2527103aaebdb58806416fd7 [file] [log] [blame]
// 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 "base/notreached.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