| // 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 |