diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 19:31:09 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-06 19:31:09 +0000 |
commit | 41f31d14541d147658b5f2c4b85a8046ab602062 (patch) | |
tree | 47dd585acc505fc4377b6469cb27ca3accf0b8bc /gpu/command_buffer | |
parent | 8ebf9b135df2b2a79cf130d39a48185b8f851338 (diff) | |
download | chromium_src-41f31d14541d147658b5f2c4b85a8046ab602062.zip chromium_src-41f31d14541d147658b5f2c4b85a8046ab602062.tar.gz chromium_src-41f31d14541d147658b5f2c4b85a8046ab602062.tar.bz2 |
Add CommandBuffer::SetGetBuffer
As well as remove CommandBuffer::GetRingBuffer and
change CommandBuffer::Initialize
Before this change the service allocated and managed the command buffer.
After this change the client uses CreateTransferBuffer, GetTransferBuffer,
end potentially DeleteTransferBufffer to manage the command buffer.
Another CL will actually make the client delete the command buffer
on demand.
TEST=unit tests and run some samples and a NaCl 3D game
BUG=103989
Review URL: http://codereview.chromium.org/8566059
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113250 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer')
21 files changed, 358 insertions, 267 deletions
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 6328923..d43efc3 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -17,6 +17,8 @@ const double kFlushDelay = 1.0 / (5.0 * 60.0); CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) : command_buffer_(command_buffer), + ring_buffer_id_(-1), + ring_buffer_size_(0), entries_(NULL), total_entry_count_(0), usable_entry_count_(0), @@ -27,14 +29,25 @@ CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) last_flush_time_(0) { } -bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { - ring_buffer_ = command_buffer_->GetRingBuffer(); +bool CommandBufferHelper::AllocateRingBuffer() { + int32 id = command_buffer_->CreateTransferBuffer(ring_buffer_size_, -1); + if (id < 0) { + return false; + } + + ring_buffer_ = command_buffer_->GetTransferBuffer(id); if (!ring_buffer_.ptr) return false; + ring_buffer_id_ = id; + command_buffer_->SetGetBuffer(id); + + // TODO(gman): Do we really need to call GetState here? We know get & put = 0 + // Also do we need to check state.num_entries? CommandBuffer::State state = command_buffer_->GetState(); entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); - int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry); + int32 num_ring_buffer_entries = + ring_buffer_size_ / sizeof(CommandBufferEntry); if (num_ring_buffer_entries > state.num_entries) { return false; } @@ -48,6 +61,11 @@ bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { return true; } +bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { + ring_buffer_size_ = ring_buffer_size; + return AllocateRingBuffer(); +} + CommandBufferHelper::~CommandBufferHelper() { } diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h index b6f45e2..5fbf462 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -214,6 +214,10 @@ class CommandBufferHelper { return command_buffer_; } + Buffer get_ring_buffer() const { + return ring_buffer_; + } + private: // Waits until get changes, updating the value of get_. void WaitForGetChange(); @@ -224,9 +228,13 @@ class CommandBufferHelper { usable_entry_count_; } + bool AllocateRingBuffer(); + CommandBuffer* command_buffer_; + int32 ring_buffer_id_; + int32 ring_buffer_size_; Buffer ring_buffer_; - CommandBufferEntry *entries_; + CommandBufferEntry* entries_; int32 total_entry_count_; // the total number of entries int32 usable_entry_count_; // the usable number (ie, minus space for jump) int32 token_; diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 3b314c4..216bb60 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -66,15 +66,9 @@ class CommandBufferHelperTest : public testing::Test { .WillRepeatedly(Return(error::kNoError)); command_buffer_.reset(new CommandBufferService); - command_buffer_->Initialize(kCommandBufferSizeBytes); - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + command_buffer_->Initialize(); - parser_ = new CommandParser(ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size, - 0, - api_mock_.get()); + parser_ = new CommandParser(api_mock_.get()); do_jump_command_.reset(new DoJumpCommand(parser_)); EXPECT_CALL(*api_mock_, DoCommand(cmd::kJump, _, _)) @@ -90,6 +84,12 @@ class CommandBufferHelperTest : public testing::Test { helper_.reset(new CommandBufferHelper(command_buffer_.get())); helper_->Initialize(kCommandBufferSizeBytes); + + // Note: parser->SetBuffer would normally be called through + // helper_->Initialize but currently it needs a GpuCommandBufferStub as the + // CommandBuffer instead of the CommandBufferService for that to happen. + Buffer ring_buffer = helper_->get_ring_buffer(); + parser_->SetBuffer(ring_buffer.ptr, ring_buffer.size, 0, ring_buffer.size); } virtual void TearDown() { diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc index 417b26a..ebd8ff6 100644 --- a/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/gpu/command_buffer/client/fenced_allocator_test.cc @@ -45,15 +45,9 @@ class BaseFencedAllocatorTest : public testing::Test { Return(error::kNoError))); command_buffer_.reset(new CommandBufferService); - command_buffer_->Initialize(kBufferSize); - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + command_buffer_->Initialize(); - parser_ = new CommandParser(ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size, - 0, - api_mock_.get()); + parser_ = new CommandParser(api_mock_.get()); gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_)); @@ -64,6 +58,12 @@ class BaseFencedAllocatorTest : public testing::Test { helper_.reset(new CommandBufferHelper(command_buffer_.get())); helper_->Initialize(kBufferSize); + + // Note: parser->SetBuffer would normally be called through + // helper_->Initialize but currently it needs a GpuCommandBufferStub as the + // CommandBuffer instead of the CommandBufferService for that to happen. + Buffer ring_buffer = helper_->get_ring_buffer(); + parser_->SetBuffer(ring_buffer.ptr, ring_buffer.size, 0, ring_buffer.size); } int32 GetToken() { diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 5ce2a8b..4c6013d 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -15,34 +15,30 @@ #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS #endif +using testing::_; +using testing::DoAll; +using testing::InSequence; +using testing::Invoke; +using testing::Mock; +using testing::Sequence; +using testing::Truly; +using testing::Return; + namespace gpu { class GLES2MockCommandBufferHelper : public CommandBuffer { public: - static const int32 kTransferBufferId = 0x123; + static const int32 kTransferBufferBaseId = 0x123; + static const int32 kMaxTransferBuffers = 6; GLES2MockCommandBufferHelper() { } virtual ~GLES2MockCommandBufferHelper() { } // CommandBuffer implementation: - virtual bool Initialize(int32 size) { - ring_buffer_.reset(new CommandBufferEntry[size]); - ring_buffer_buffer_.ptr = ring_buffer_.get(); - ring_buffer_buffer_.size = size; - state_.num_entries = size / sizeof(ring_buffer_[0]); - state_.token = 10000; // All token checks in the tests should pass. + virtual bool Initialize() { return true; } - virtual bool Initialize(base::SharedMemory* buffer, int32 size) { - GPU_NOTREACHED(); - return false; - } - - virtual Buffer GetRingBuffer() { - return ring_buffer_buffer_; - } - virtual State GetState() { return state_; } @@ -58,28 +54,57 @@ class GLES2MockCommandBufferHelper : public CommandBuffer { virtual State FlushSync(int32 put_offset, int32 last_known_get) { state_.put_offset = put_offset; state_.get_offset = put_offset; - OnFlush(transfer_buffer_buffer_.ptr); + // Warning: This is a hack. We just happen to know that the default + // transfer buffer will be the first transfer buffer. + OnFlush(transfer_buffer_buffers_[0].ptr); return state_; } + virtual void SetGetBuffer(int transfer_buffer_id) { + ring_buffer_buffer_ = GetTransferBuffer(transfer_buffer_id); + ring_buffer_ = static_cast<CommandBufferEntry*>(ring_buffer_buffer_.ptr); + state_.num_entries = ring_buffer_buffer_.size / sizeof(ring_buffer_[0]); + state_.token = 10000; // All token checks in the tests should pass. + } + virtual void SetGetOffset(int32 get_offset) { state_.get_offset = get_offset; } + // Get's the Id of the next transfer buffer that will be returned + // by CreateTransferBuffer. This is useful for testing expected ids. + int32 GetNextFreeTransferBufferId() { + for (size_t ii = 0; ii < arraysize(transfer_buffers_); ++ii) { + if (!transfer_buffers_[ii].get()) { + return kTransferBufferBaseId + ii; + } + } + return -1; + } + virtual int32 CreateTransferBuffer(size_t size, int32 id_request) { - transfer_buffer_.reset(new int8[size]); - transfer_buffer_buffer_.ptr = transfer_buffer_.get(); - transfer_buffer_buffer_.size = size; - return kTransferBufferId; + int32 id = GetNextFreeTransferBufferId(); + if (id >= 0) { + int32 ndx = id - kTransferBufferBaseId; + transfer_buffers_[ndx].reset(new int8[size]); + transfer_buffer_buffers_[ndx].ptr = transfer_buffers_[ndx].get(); + transfer_buffer_buffers_[ndx].size = size; + } + return id; } - virtual void DestroyTransferBuffer(int32 /* id */) { - GPU_NOTREACHED(); + void DestroyTransferBufferHelper(int32 id) { + GPU_DCHECK_GE(id, kTransferBufferBaseId); + GPU_DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers); + id -= kTransferBufferBaseId; + transfer_buffers_[id].reset(); + transfer_buffer_buffers_[id] = Buffer(); } virtual Buffer GetTransferBuffer(int32 id) { - GPU_DCHECK_EQ(id, kTransferBufferId); - return transfer_buffer_buffer_; + GPU_DCHECK_GE(id, kTransferBufferBaseId); + GPU_DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers); + return transfer_buffer_buffers_[id - kTransferBufferBaseId]; } virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory, @@ -107,39 +132,41 @@ class GLES2MockCommandBufferHelper : public CommandBuffer { virtual void OnFlush(void* transfer_buffer) = 0; private: - scoped_array<int8> transfer_buffer_; - Buffer transfer_buffer_buffer_; - scoped_array<CommandBufferEntry> ring_buffer_; + scoped_array<int8> transfer_buffers_[kMaxTransferBuffers]; + Buffer transfer_buffer_buffers_[kMaxTransferBuffers]; + CommandBufferEntry* ring_buffer_; Buffer ring_buffer_buffer_; State state_; }; class MockGLES2CommandBuffer : public GLES2MockCommandBufferHelper { public: + MockGLES2CommandBuffer() { + DelegateToFake(); + } + virtual ~MockGLES2CommandBuffer() { } // This is so we can use all the gmock functions when Flush is called. MOCK_METHOD1(OnFlush, void(void* result)); MOCK_METHOD1(DestroyTransferBuffer, void(int32 id)); + + void DelegateToFake() { + ON_CALL(*this, DestroyTransferBuffer(_)) + .WillByDefault(Invoke( + this, &GLES2MockCommandBufferHelper::DestroyTransferBufferHelper)); + } }; // GCC requires these declarations, but MSVC requires they not be present #ifndef _MSC_VER -const int32 GLES2MockCommandBufferHelper::kTransferBufferId; +const int32 GLES2MockCommandBufferHelper::kTransferBufferBaseId; +const int32 GLES2MockCommandBufferHelper::kMaxTransferBuffers; #endif namespace gles2 { -using testing::_; -using testing::DoAll; -using testing::InSequence; -using testing::Invoke; -using testing::Mock; -using testing::Sequence; -using testing::Truly; -using testing::Return; - ACTION_P(SetMemory, obj) { memcpy(arg0, &obj, sizeof(obj)); } @@ -194,8 +221,6 @@ class GLES2CommandBufferTestBase : public testing::Test { static const int32 kCommandBufferSizeBytes = kNumCommandEntries * sizeof(CommandBufferEntry); static const size_t kTransferBufferSize = 256; - static const int32 kTransferBufferId = - GLES2MockCommandBufferHelper::kTransferBufferId; static const uint8 kInitialValue = 0xBD; GLES2CommandBufferTestBase() @@ -203,7 +228,8 @@ class GLES2CommandBufferTestBase : public testing::Test { token_(0), offset_(0), initial_offset_(0), - alignment_(0) { + alignment_(0), + transfer_buffer_id_(-1) { } void SetupCommandBuffer(unsigned int offset, unsigned alignment) { @@ -212,11 +238,11 @@ class GLES2CommandBufferTestBase : public testing::Test { alignment_ = alignment; command_buffer_.reset(new MockGLES2CommandBuffer()); - command_buffer_->Initialize(kCommandBufferSizeBytes); + command_buffer_->Initialize(); - EXPECT_EQ(kTransferBufferId, - command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1)); - transfer_buffer_ = command_buffer_->GetTransferBuffer(kTransferBufferId); + transfer_buffer_id_ = + command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1); + transfer_buffer_ = command_buffer_->GetTransferBuffer(transfer_buffer_id_); ClearTransferBuffer(); helper_.reset(new GLES2CmdHelper(command_buffer_.get())); @@ -232,7 +258,7 @@ class GLES2CommandBufferTestBase : public testing::Test { } void ClearCommands() { - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + Buffer ring_buffer = helper_->get_ring_buffer(); memset(ring_buffer.ptr, kInitialValue, ring_buffer.size); } @@ -253,6 +279,10 @@ class GLES2CommandBufferTestBase : public testing::Test { return ++token_; } + int32 GetNextFreeTransferBufferId() { + return command_buffer_->GetNextFreeTransferBufferId(); + } + uint32 AllocateTransferBuffer(size_t size) { if (offset_ + size > kTransferBufferSize) { offset_ = initial_offset_; @@ -280,6 +310,7 @@ class GLES2CommandBufferTestBase : public testing::Test { uint32 offset_; uint32 initial_offset_; uint32 alignment_; + int32 transfer_buffer_id_; }; // GCC requires these declarations, but MSVC requires they not be present @@ -287,7 +318,6 @@ class GLES2CommandBufferTestBase : public testing::Test { const int32 GLES2CommandBufferTestBase::kNumCommandEntries; const int32 GLES2CommandBufferTestBase::kCommandBufferSizeBytes; const size_t GLES2CommandBufferTestBase::kTransferBufferSize; -const int32 GLES2CommandBufferTestBase::kTransferBufferId; const uint8 GLES2CommandBufferTestBase::kInitialValue; #endif @@ -303,9 +333,12 @@ class TransferBufferTest : public GLES2CommandBufferTestBase { GLES2Implementation::kStartingOffset, GLES2Implementation::kAlignment); + transfer_buffer_id_ = + command_buffer_->CreateTransferBuffer(kTransferBufferSize, -1); + transfer_buffer_.reset(new TransferBuffer( helper_.get(), - kTransferBufferId, + transfer_buffer_id_, GetTransferAddressFromOffset(0, 0), kTransferBufferSize, kStartingOffset, @@ -327,7 +360,7 @@ const unsigned int TransferBufferTest::kAlignment; TEST_F(TransferBufferTest, Basic) { EXPECT_TRUE(transfer_buffer_->HaveBuffer()); - EXPECT_EQ(kTransferBufferId, transfer_buffer_->GetShmId()); + EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); } TEST_F(TransferBufferTest, Free) { @@ -341,7 +374,7 @@ TEST_F(TransferBufferTest, Free) { // See it's freed. EXPECT_FALSE(transfer_buffer_->HaveBuffer()); // See that it gets reallocated. - EXPECT_EQ(kTransferBufferId, transfer_buffer_->GetShmId()); + EXPECT_EQ(transfer_buffer_id_, transfer_buffer_->GetShmId()); EXPECT_TRUE(transfer_buffer_->HaveBuffer()); // Free buffer. @@ -473,7 +506,7 @@ class GLES2ImplementationTest : public GLES2CommandBufferTestBase { helper_.get(), kTransferBufferSize, transfer_buffer_.ptr, - kTransferBufferId, + transfer_buffer_id_, shared_resources, bind_generates_resource)); } @@ -482,7 +515,7 @@ class GLES2ImplementationTest : public GLES2CommandBufferTestBase { .Times(1) .RetiresOnSaturation(); helper_->CommandBufferHelper::Finish(); - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + Buffer ring_buffer = helper_->get_ring_buffer(); commands_ = static_cast<CommandBufferEntry*>(ring_buffer.ptr) + command_buffer_->GetState().put_offset; ClearCommands(); @@ -525,16 +558,16 @@ TEST_F(GLES2ImplementationTest, ShaderSource) { Cmds expected; expected.set_bucket_size.Init(kBucketId, kSourceSize); expected.set_bucket_data1.Init( - kBucketId, 0, kString1Size, kTransferBufferId, + kBucketId, 0, kString1Size, transfer_buffer_id_, AllocateTransferBuffer(kPaddedString1Size)); expected.set_token1.Init(GetNextToken()); expected.set_bucket_data2.Init( - kBucketId, kString1Size, kString2Size, kTransferBufferId, + kBucketId, kString1Size, kString2Size, transfer_buffer_id_, AllocateTransferBuffer(kPaddedString2Size)); expected.set_token2.Init(GetNextToken()); expected.set_bucket_data3.Init( kBucketId, kString1Size + kString2Size, - kString3Size, kTransferBufferId, + kString3Size, transfer_buffer_id_, AllocateTransferBuffer(kPaddedString3Size)); expected.set_token3.Init(GetNextToken()); expected.shader_source_bucket.Init(kShaderId, kBucketId); @@ -564,9 +597,9 @@ TEST_F(GLES2ImplementationTest, GetShaderSource) { Cmds expected; expected.set_bucket_size1.Init(kBucketId, 0); expected.get_shader_source.Init(kShaderId, kBucketId); - expected.get_bucket_size.Init(kBucketId, kTransferBufferId, 0); + expected.get_bucket_size.Init(kBucketId, transfer_buffer_id_, 0); expected.get_bucket_data.Init( - kBucketId, 0, sizeof(kString), kTransferBufferId, offset); + kBucketId, 0, sizeof(kString), transfer_buffer_id_, offset); expected.set_token1.Init(GetNextToken()); expected.set_bucket_size2.Init(kBucketId, 0); char buf[sizeof(kString) + 1]; @@ -628,13 +661,13 @@ TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) { expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); expected.copy_data1.Init( - GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, transfer_buffer_id_, AllocateTransferBuffer(kSize1)); expected.set_token1.Init(GetNextToken()); expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); expected.copy_data2.Init( - GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, transfer_buffer_id_, AllocateTransferBuffer(kSize2)); expected.set_token2.Init(GetNextToken()); expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, @@ -704,19 +737,19 @@ TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) { expected.set_index_size.Init( GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW); expected.copy_data0.Init( - GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, kTransferBufferId, + GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, transfer_buffer_id_, AllocateTransferBuffer(kIndexSize)); expected.set_token0.Init(GetNextToken()); expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); expected.copy_data1.Init( - GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, transfer_buffer_id_, AllocateTransferBuffer(kSize1)); expected.set_token1.Init(GetNextToken()); expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); expected.copy_data2.Init( - GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, transfer_buffer_id_, AllocateTransferBuffer(kSize2)); expected.set_token2.Init(GetNextToken()); expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, @@ -780,17 +813,17 @@ TEST_F(GLES2ImplementationTest, expected.enable2.Init(kAttribIndex2); expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId); expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT, - kIndexOffset, kTransferBufferId, 0); + kIndexOffset, transfer_buffer_id_, 0); expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId); expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW); expected.copy_data1.Init( - GL_ARRAY_BUFFER, kEmuOffset1, kSize1, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset1, kSize1, transfer_buffer_id_, AllocateTransferBuffer(kSize1)); expected.set_token1.Init(GetNextToken()); expected.set_pointer1.Init(kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1); expected.copy_data2.Init( - GL_ARRAY_BUFFER, kEmuOffset2, kSize2, kTransferBufferId, + GL_ARRAY_BUFFER, kEmuOffset2, kSize2, transfer_buffer_id_, AllocateTransferBuffer(kSize2)); expected.set_token2.Init(GetNextToken()); expected.set_pointer2.Init(kAttribIndex2, kNumComponents2, @@ -837,7 +870,7 @@ TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) { expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kStride2, kOffset2); expected.get_pointer.Init(kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, - kTransferBufferId, 0); + transfer_buffer_id_, 0); // One call to flush to way for GetVertexAttribPointerv EXPECT_CALL(*command_buffer_, OnFlush(_)) @@ -894,10 +927,10 @@ TEST_F(GLES2ImplementationTest, GetVertexAttrib) { kStride2, kOffset2); expected.get1.Init(kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, - kTransferBufferId, 0); + transfer_buffer_id_, 0); expected.get2.Init(kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, - kTransferBufferId, 0); + transfer_buffer_id_, 0); FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f); @@ -960,7 +993,7 @@ TEST_F(GLES2ImplementationTest, ReservedIds) { GetError get; }; Cmds expected; - expected.get.Init(kTransferBufferId, 0); + expected.get.Init(transfer_buffer_id_, 0); // One call to flush to wait for GetError EXPECT_CALL(*command_buffer_, OnFlush(_)) @@ -998,15 +1031,15 @@ TEST_F(GLES2ImplementationTest, ReadPixels2Reads) { Cmds expected; expected.read1.Init( 0, 0, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, + transfer_buffer_id_, AllocateTransferBuffer(kWidth * kHeight / 2 * kBytesPerPixel), - kTransferBufferId, 0); + transfer_buffer_id_, 0); expected.set_token1.Init(GetNextToken()); expected.read2.Init( 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, + transfer_buffer_id_, AllocateTransferBuffer(kWidth * kHeight / 2 * kBytesPerPixel), - kTransferBufferId, 0); + transfer_buffer_id_, 0); expected.set_token2.Init(GetNextToken()); scoped_array<int8> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); @@ -1033,9 +1066,9 @@ TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) { Cmds expected; expected.read.Init( 0, 0, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, + transfer_buffer_id_, AllocateTransferBuffer(kWidth * kHeight * kBytesPerPixel), - kTransferBufferId, 0); + transfer_buffer_id_, 0); expected.set_token.Init(GetNextToken()); scoped_array<int8> buffer(new int8[kWidth * kHeight * kBytesPerPixel]); @@ -1058,7 +1091,7 @@ TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) { uint32 offset = 0; Cmds expected; expected.buf.Init( - kTarget, kOffset, kSize, kTransferBufferId, offset); + kTarget, kOffset, kSize, transfer_buffer_id_, offset); expected.set_token.Init(GetNextToken()); void* mem = gl_->MapBufferSubDataCHROMIUM( @@ -1083,7 +1116,7 @@ TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) { uint32 offset = 0; Cmds expected; expected.buf.Init( - kTarget, kOffset, kSize, kTransferBufferId, offset); + kTarget, kOffset, kSize, GetNextFreeTransferBufferId(), offset); expected.set_token.Init(GetNextToken()); void* mem = gl_->MapBufferSubDataCHROMIUM( @@ -1138,7 +1171,7 @@ TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) { Cmds expected; expected.tex.Init( GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat, - kType, kTransferBufferId, offset, GL_FALSE); + kType, GetNextFreeTransferBufferId(), offset, GL_FALSE); expected.set_token.Init(GetNextToken()); void* mem = gl_->MapTexSubImage2DCHROMIUM( @@ -1273,8 +1306,8 @@ TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMValidArgs) { const uint32 kResultsOffset = AllocateTransferBuffer(kResultsSize); Cmds expected; expected.get_multiple.Init( - kTransferBufferId, kPnamesOffset, kNumPnames, - kTransferBufferId, kResultsOffset, kResultsSize); + transfer_buffer_id_, kPnamesOffset, kNumPnames, + transfer_buffer_id_, kResultsOffset, kResultsSize); expected.set_token.Init(GetNextToken()); const GLint kSentinel = 0x12345678; @@ -1383,9 +1416,9 @@ TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) { Cmds expected; expected.set_bucket_size1.Init(kBucketId, 0); expected.get_program_info.Init(kProgramId, kBucketId); - expected.get_bucket_size.Init(kBucketId, kTransferBufferId, 0); + expected.get_bucket_size.Init(kBucketId, transfer_buffer_id_, 0); expected.get_bucket_data.Init( - kBucketId, 0, sizeof(kString), kTransferBufferId, offset); + kBucketId, 0, sizeof(kString), transfer_buffer_id_, offset); expected.set_token1.Init(GetNextToken()); expected.set_bucket_size2.Init(kBucketId, 0); gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf); @@ -1424,9 +1457,9 @@ TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) { Cmds expected; expected.set_bucket_size1.Init(kBucketId, 0); expected.get_program_info.Init(kProgramId, kBucketId); - expected.get_bucket_size.Init(kBucketId, kTransferBufferId, 0); + expected.get_bucket_size.Init(kBucketId, transfer_buffer_id_, 0); expected.get_bucket_data.Init( - kBucketId, 0, sizeof(kString), kTransferBufferId, offset); + kBucketId, 0, sizeof(kString), transfer_buffer_id_, offset); expected.set_token1.Init(GetNextToken()); expected.set_bucket_size2.Init(kBucketId, 0); gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf); @@ -1602,7 +1635,7 @@ TEST_F(GLES2ImplementationTest, TexImage2D) { Cmds expected; expected.tex_image_2d.Init( kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, - kTransferBufferId, offset); + transfer_buffer_id_, offset); expected.set_token.Init(GetNextToken()); gl_->TexImage2D( kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, @@ -1617,7 +1650,7 @@ TEST_F(GLES2ImplementationTest, TexImage2D) { Cmds2 expected2; expected2.tex_image_2d.Init( kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType, - kTransferBufferId, offset2); + transfer_buffer_id_, offset2); expected2.set_token.Init(GetNextToken()); const void* commands2 = GetPut(); gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE); @@ -1674,11 +1707,11 @@ TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { 0, 0); expected.tex_sub_image_2d1.Init( kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, offset1, true); + transfer_buffer_id_, offset1, true); expected.set_token1.Init(GetNextToken()); expected.tex_sub_image_2d2.Init( kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, offset2, true); + transfer_buffer_id_, offset2, true); expected.set_token2.Init(GetNextToken()); // TODO(gman): Make it possible to run this test @@ -1707,11 +1740,11 @@ TEST_F(GLES2ImplementationTest, TexImage2D2Writes) { 0, 0); expected.tex_sub_image_2d1.Init( kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, offset3, true); + transfer_buffer_id_, offset3, true); expected.set_token1.Init(GetNextToken()); expected.tex_sub_image_2d2.Init( kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType, - kTransferBufferId, offset4, true); + transfer_buffer_id_, offset4, true); expected.set_token2.Init(GetNextToken()); // TODO(gman): Make it possible to run this test @@ -1777,19 +1810,19 @@ TEST_F(GLES2ImplementationTest, TexImage2DSubRows) { 0, 0); expected.tex_sub_image_2d1.Init( kTarget, kLevel, 0, 0, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset1, true); + transfer_buffer_id_, offset1, true); expected.set_token1.Init(GetNextToken()); expected.tex_sub_image_2d2.Init( kTarget, kLevel, kWidth / 2, 0, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset2, true); + transfer_buffer_id_, offset2, true); expected.set_token2.Init(GetNextToken()); expected.tex_sub_image_2d3.Init( kTarget, kLevel, 0, 1, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset3, true); + transfer_buffer_id_, offset3, true); expected.set_token3.Init(GetNextToken()); expected.tex_sub_image_2d4.Init( kTarget, kLevel, kWidth / 2, 1, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset4, true); + transfer_buffer_id_, offset4, true); expected.set_token4.Init(GetNextToken()); // TODO(gman): Make it possible to run this test @@ -1828,19 +1861,19 @@ TEST_F(GLES2ImplementationTest, TexImage2DSubRows) { 0, 0); expected.tex_sub_image_2d1.Init( kTarget, kLevel, 0, 1, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset1, true); + transfer_buffer_id_, offset1, true); expected.set_token1.Init(GetNextToken()); expected.tex_sub_image_2d2.Init( kTarget, kLevel, kWidth / 2, 1, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset2, true); + transfer_buffer_id_, offset2, true); expected.set_token2.Init(GetNextToken()); expected.tex_sub_image_2d3.Init( kTarget, kLevel, 0, 0, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset3, true); + transfer_buffer_id_, offset3, true); expected.set_token3.Init(GetNextToken()); expected.tex_sub_image_2d4.Init( kTarget, kLevel, kWidth / 2, 0, kWidth / 2, 1, kFormat, kType, - kTransferBufferId, offset4, true); + transfer_buffer_id_, offset4, true); expected.set_token4.Init(GetNextToken()); // TODO(gman): Make it possible to run this test @@ -1908,10 +1941,10 @@ TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) { kType, 0, NULL); expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset, kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType, - kTransferBufferId, offset1, false); + transfer_buffer_id_, offset1, false); expected.set_token1.Init(GetNextToken()); expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset, - kSubImageYOffset, kSubImageWidth , 2, kFormat, kType, kTransferBufferId, + kSubImageYOffset, kSubImageWidth , 2, kFormat, kType, transfer_buffer_id_, offset2, false); expected.set_token2.Init(GetNextToken()); @@ -2020,7 +2053,7 @@ TEST_F(GLES2ImplementationTest, CreateStreamTextureCHROMIUM) { }; Cmds expected; - expected.create_stream.Init(kTextureId, kTransferBufferId, kResultOffset); + expected.create_stream.Init(kTextureId, transfer_buffer_id_, kResultOffset); EXPECT_CALL(*command_buffer_, OnFlush(_)) .WillOnce(SetMemoryAtOffset(kResultOffset, kResult)) diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc index 81b6655..c18ec9f 100644 --- a/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -42,15 +42,9 @@ class MappedMemoryTestBase : public testing::Test { Return(error::kNoError))); command_buffer_.reset(new CommandBufferService); - command_buffer_->Initialize(kBufferSize); - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + command_buffer_->Initialize(); - parser_ = new CommandParser(ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size, - 0, - api_mock_.get()); + parser_ = new CommandParser(api_mock_.get()); gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_)); @@ -61,6 +55,12 @@ class MappedMemoryTestBase : public testing::Test { helper_.reset(new CommandBufferHelper(command_buffer_.get())); helper_->Initialize(kBufferSize); + + // Note: parser->SetBuffer would normally be called through + // helper_->Initialize but currently it needs a GpuCommandBufferStub as the + // CommandBuffer instead of the CommandBufferService for that to happen. + Buffer ring_buffer = helper_->get_ring_buffer(); + parser_->SetBuffer(ring_buffer.ptr, ring_buffer.size, 0, ring_buffer.size); } int32 GetToken() { diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc index eb5a0cb..8b8e46e 100644 --- a/gpu/command_buffer/client/ring_buffer_test.cc +++ b/gpu/command_buffer/client/ring_buffer_test.cc @@ -65,15 +65,9 @@ class BaseRingBufferTest : public testing::Test { Return(error::kNoError))); command_buffer_.reset(new CommandBufferService); - command_buffer_->Initialize(kBufferSize); - Buffer ring_buffer = command_buffer_->GetRingBuffer(); + command_buffer_->Initialize(); - parser_ = new CommandParser(ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size, - 0, - api_mock_.get()); + parser_ = new CommandParser(api_mock_.get()); gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_)); @@ -88,6 +82,12 @@ class BaseRingBufferTest : public testing::Test { helper_.reset(new CommandBufferHelper(command_buffer_.get())); helper_->Initialize(kBufferSize); + + // Note: parser->SetBuffer would normally be called through + // helper_->Initialize but currently it needs a GpuCommandBufferStub as the + // CommandBuffer instead of the CommandBufferService for that to happen. + Buffer ring_buffer = helper_->get_ring_buffer(); + parser_->SetBuffer(ring_buffer.ptr, ring_buffer.size, 0, ring_buffer.size); } int32 GetToken() { diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h index 76124c8..e44df7f 100644 --- a/gpu/command_buffer/common/command_buffer.h +++ b/gpu/command_buffer/common/command_buffer.h @@ -67,13 +67,7 @@ class CommandBuffer { } // Initialize the command buffer with the given size. - virtual bool Initialize(int32 size) = 0; - - // Initialize the command buffer using the given preallocated buffer. - virtual bool Initialize(base::SharedMemory* buffer, int32 size) = 0; - - // Gets the ring buffer for the command buffer. - virtual Buffer GetRingBuffer() = 0; + virtual bool Initialize() = 0; // Returns the current status. virtual State GetState() = 0; @@ -92,6 +86,10 @@ class CommandBuffer { // have been executed. virtual State FlushSync(int32 put_offset, int32 last_known_get) = 0; + // Sets the buffer commands are read from. + // Also resets the get and put offsets to 0. + virtual void SetGetBuffer(int32 transfer_buffer_id) = 0; + // Sets the current get offset. This can be called from any thread. virtual void SetGetOffset(int32 get_offset) = 0; diff --git a/gpu/command_buffer/common/command_buffer_mock.cc b/gpu/command_buffer/common/command_buffer_mock.cc index d92c2c3..6ed2eee 100644 --- a/gpu/command_buffer/common/command_buffer_mock.cc +++ b/gpu/command_buffer/common/command_buffer_mock.cc @@ -7,8 +7,6 @@ namespace gpu { MockCommandBuffer::MockCommandBuffer() { - ON_CALL(*this, GetRingBuffer()) - .WillByDefault(testing::Return(Buffer())); ON_CALL(*this, GetTransferBuffer(testing::_)) .WillByDefault(testing::Return(Buffer())); } diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h index 321c40d..0379340 100644 --- a/gpu/command_buffer/common/command_buffer_mock.h +++ b/gpu/command_buffer/common/command_buffer_mock.h @@ -21,13 +21,12 @@ class MockCommandBuffer : public CommandBuffer { MockCommandBuffer(); virtual ~MockCommandBuffer(); - MOCK_METHOD1(Initialize, bool(int32 size)); - MOCK_METHOD2(Initialize, bool(base::SharedMemory* buffer, int32 size)); - MOCK_METHOD0(GetRingBuffer, Buffer()); + MOCK_METHOD0(Initialize, bool()); MOCK_METHOD0(GetState, State()); MOCK_METHOD0(GetLastState, State()); MOCK_METHOD1(Flush, void(int32 put_offset)); MOCK_METHOD2(FlushSync, State(int32 put_offset, int32 last_known_get)); + MOCK_METHOD1(SetGetBuffer, void(int32 transfer_buffer_id)); MOCK_METHOD1(SetGetOffset, void(int32 get_offset)); MOCK_METHOD2(CreateTransferBuffer, int32(size_t size, int32 id_request)); MOCK_METHOD1(DestroyTransferBuffer, void(int32 handle)); diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h index 59e99ab..6aefe82 100644 --- a/gpu/command_buffer/service/cmd_buffer_engine.h +++ b/gpu/command_buffer/service/cmd_buffer_engine.h @@ -29,6 +29,9 @@ class CommandBufferEngine { // Sets the token value. virtual void set_token(int32 token) = 0; + // Sets the shared memory buffer used for commands. + virtual bool SetGetBuffer(int32 transfer_buffer_id) = 0; + // Sets the "get" pointer. Return false if offset is out of range. virtual bool SetGetOffset(int32 offset) = 0; diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc index fba06e6..b5383af 100644 --- a/gpu/command_buffer/service/cmd_parser.cc +++ b/gpu/command_buffer/service/cmd_parser.cc @@ -10,23 +10,29 @@ namespace gpu { -CommandParser::CommandParser(void *shm_address, - size_t shm_size, - ptrdiff_t offset, - size_t size, - CommandBufferOffset start_get, - AsyncAPIInterface *handler) - : get_(start_get), - put_(start_get), +CommandParser::CommandParser(AsyncAPIInterface* handler) + : get_(0), + put_(0), + buffer_(NULL), + entry_count_(0), handler_(handler) { +} + +void CommandParser::SetBuffer( + void* shm_address, + size_t shm_size, + ptrdiff_t offset, + size_t size) { // check proper alignments. DCHECK_EQ(0, (reinterpret_cast<intptr_t>(shm_address)) % 4); DCHECK_EQ(0, offset % 4); DCHECK_EQ(0u, size % 4); // check that the command buffer fits into the memory buffer. DCHECK_GE(shm_size, offset + size); - char * buffer_begin = static_cast<char *>(shm_address) + offset; - buffer_ = reinterpret_cast<CommandBufferEntry *>(buffer_begin); + get_ = 0; + put_ = 0; + char* buffer_begin = static_cast<char*>(shm_address) + offset; + buffer_ = reinterpret_cast<CommandBufferEntry*>(buffer_begin); entry_count_ = size / 4; } diff --git a/gpu/command_buffer/service/cmd_parser.h b/gpu/command_buffer/service/cmd_parser.h index fe3eb12..567b7f6 100644 --- a/gpu/command_buffer/service/cmd_parser.h +++ b/gpu/command_buffer/service/cmd_parser.h @@ -18,12 +18,14 @@ class AsyncAPIInterface; // buffer, to implement some asynchronous RPC mechanism. class CommandParser { public: - CommandParser(void *shm_address, - size_t shm_size, - ptrdiff_t offset, - size_t size, - CommandBufferOffset start_get, - AsyncAPIInterface *handler); + explicit CommandParser(AsyncAPIInterface* handler); + + // Sets the buffer to read commands from. + void SetBuffer( + void* shm_address, + size_t shm_size, + ptrdiff_t offset, + size_t size); // Gets the "get" pointer. The get pointer is an index into the command // buffer considered as an array of CommandBufferEntry. @@ -63,9 +65,9 @@ class CommandParser { private: CommandBufferOffset get_; CommandBufferOffset put_; - CommandBufferEntry *buffer_; + CommandBufferEntry* buffer_; int32 entry_count_; - AsyncAPIInterface *handler_; + AsyncAPIInterface* handler_; }; // This class defines the interface for an asynchronous API handler, that diff --git a/gpu/command_buffer/service/cmd_parser_test.cc b/gpu/command_buffer/service/cmd_parser_test.cc index 857ca8e..b86b0af 100644 --- a/gpu/command_buffer/service/cmd_parser_test.cc +++ b/gpu/command_buffer/service/cmd_parser_test.cc @@ -48,12 +48,10 @@ class CommandParserTest : public testing::Test { size_t command_buffer_size = entry_count * sizeof(CommandBufferEntry); // NOLINT DCHECK_LE(command_buffer_size, shm_size); - return new CommandParser(buffer(), - shm_size, - 0, - command_buffer_size, - 0, - api_mock()); + CommandParser* parser = new CommandParser(api_mock()); + + parser->SetBuffer(buffer(), shm_size, 0, command_buffer_size); + return parser; } unsigned int buffer_entry_count() { return 20; } @@ -288,4 +286,34 @@ TEST_F(CommandParserTest, TestError) { Mock::VerifyAndClearExpectations(api_mock()); } +TEST_F(CommandParserTest, SetBuffer) { + scoped_ptr<CommandParser> parser(MakeParser(3)); + CommandBufferOffset put = parser->put(); + CommandHeader header; + + // add a single command, no args + header.size = 2; + header.command = 123; + buffer()[put++].value_header = header; + buffer()[put++].value_int32 = 456; + + CommandBufferEntry param_array[1]; + param_array[0].value_int32 = 456; + + parser->set_put(put); + AddDoCommandExpect(error::kNoError, 123, 1, param_array); + EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); + // We should have advanced 2 entries + EXPECT_EQ(2, parser->get()); + Mock::VerifyAndClearExpectations(api_mock()); + + scoped_array<CommandBufferEntry> buffer2(new CommandBufferEntry[2]); + parser->SetBuffer( + buffer2.get(), sizeof(CommandBufferEntry) * 2, 0, + sizeof(CommandBufferEntry) * 2); + // The put and get should have reset to 0. + EXPECT_EQ(0, parser->get()); + EXPECT_EQ(0, parser->put()); +} + } // namespace gpu diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc index d126883..7ad5994 100644 --- a/gpu/command_buffer/service/command_buffer_service.cc +++ b/gpu/command_buffer/service/command_buffer_service.cc @@ -14,7 +14,8 @@ using ::base::SharedMemory; namespace gpu { CommandBufferService::CommandBufferService() - : num_entries_(0), + : ring_buffer_id_(-1), + num_entries_(0), get_offset_(0), put_offset_(0), token_(0), @@ -25,71 +26,16 @@ CommandBufferService::CommandBufferService() } CommandBufferService::~CommandBufferService() { - delete ring_buffer_.shared_memory; - for (size_t i = 0; i < registered_objects_.size(); ++i) { if (registered_objects_[i].shared_memory) delete registered_objects_[i].shared_memory; } } -bool CommandBufferService::Initialize(int32 size) { - // Fail if already initialized. - if (ring_buffer_.shared_memory) { - LOG(ERROR) << "Failed because already initialized."; - return false; - } - - if (size <= 0 || size > kMaxCommandBufferSize) { - LOG(ERROR) << "Failed because command buffer size was invalid."; - return false; - } - - num_entries_ = size / sizeof(CommandBufferEntry); - - SharedMemory shared_memory; - if (!shared_memory.CreateAnonymous(size)) { - LOG(ERROR) << "Failed to create shared memory for command buffer."; - return true; - } - - return Initialize(&shared_memory, size); -} - -bool CommandBufferService::Initialize(base::SharedMemory* buffer, int32 size) { - // Fail if already initialized. - if (ring_buffer_.shared_memory) { - LOG(ERROR) << "Failed because already initialized."; - return false; - } - - base::SharedMemoryHandle shared_memory_handle; - if (!buffer->ShareToProcess(base::GetCurrentProcessHandle(), - &shared_memory_handle)) { - LOG(ERROR) << "Failed to duplicate command buffer shared memory handle."; - return false; - } - - ring_buffer_.shared_memory = new base::SharedMemory(shared_memory_handle, - false); - if (!ring_buffer_.shared_memory->Map(size)) { - LOG(ERROR) << "Failed because ring buffer could not be created or mapped "; - delete ring_buffer_.shared_memory; - ring_buffer_.shared_memory = NULL; - return false; - } - - ring_buffer_.ptr = ring_buffer_.shared_memory->memory(); - ring_buffer_.size = size; - num_entries_ = size / sizeof(CommandBufferEntry); - +bool CommandBufferService::Initialize() { return true; } -Buffer CommandBufferService::GetRingBuffer() { - return ring_buffer_; -} - CommandBufferService::State CommandBufferService::GetState() { State state; state.num_entries = num_entries_; @@ -134,6 +80,17 @@ void CommandBufferService::Flush(int32 put_offset) { put_offset_change_callback_.Run(); } +void CommandBufferService::SetGetBuffer(int32 transfer_buffer_id) { + DCHECK_EQ(-1, ring_buffer_id_); + DCHECK_EQ(put_offset_, get_offset_); // Only if it's empty. + ring_buffer_ = GetTransferBuffer(transfer_buffer_id); + DCHECK(ring_buffer_.ptr); + ring_buffer_id_ = transfer_buffer_id; + num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry); + put_offset_ = 0; + SetGetOffset(0); +} + void CommandBufferService::SetGetOffset(int32 get_offset) { DCHECK(get_offset >= 0 && get_offset < num_entries_); get_offset_ = get_offset; @@ -223,6 +180,14 @@ void CommandBufferService::DestroyTransferBuffer(int32 handle) { registered_objects_[handle] = Buffer(); unused_registered_object_elements_.insert(handle); + if (handle == ring_buffer_id_) { + ring_buffer_id_ = -1; + ring_buffer_ = Buffer(); + num_entries_ = 0; + get_offset_ = 0; + put_offset_ = 0; + } + // Remove all null objects from the end of the vector. This allows the vector // to shrink when, for example, all objects are unregistered. Note that this // loop never removes element zero, which is always NULL. diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h index b48bd90..187c785 100644 --- a/gpu/command_buffer/service/command_buffer_service.h +++ b/gpu/command_buffer/service/command_buffer_service.h @@ -25,13 +25,12 @@ class CommandBufferService : public CommandBuffer { virtual ~CommandBufferService(); // CommandBuffer implementation: - virtual bool Initialize(int32 size) OVERRIDE; - virtual bool Initialize(base::SharedMemory* buffer, int32 size) OVERRIDE; - virtual Buffer GetRingBuffer() OVERRIDE; + virtual bool Initialize() OVERRIDE; virtual State GetState() OVERRIDE; virtual State GetLastState() OVERRIDE; virtual void Flush(int32 put_offset) OVERRIDE; virtual State FlushSync(int32 put_offset, int32 last_known_get) OVERRIDE; + virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; virtual void SetGetOffset(int32 get_offset) OVERRIDE; virtual int32 CreateTransferBuffer(size_t size, int32 id_request) OVERRIDE; virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory, @@ -55,6 +54,7 @@ class CommandBufferService : public CommandBuffer { virtual void SetParseErrorCallback(const base::Closure& callback); private: + int32 ring_buffer_id_; Buffer ring_buffer_; int32 num_entries_; int32 get_offset_; diff --git a/gpu/command_buffer/service/common_decoder_unittest.cc b/gpu/command_buffer/service/common_decoder_unittest.cc index a240948..571ffa0 100644 --- a/gpu/command_buffer/service/common_decoder_unittest.cc +++ b/gpu/command_buffer/service/common_decoder_unittest.cc @@ -116,6 +116,12 @@ class MockCommandBufferEngine : public CommandBufferEngine { } // Overridden from CommandBufferEngine. + virtual bool SetGetBuffer(int32 transfer_buffer_id) { + NOTREACHED(); + return false; + } + + // Overridden from CommandBufferEngine. virtual bool SetGetOffset(int32 offset) { if (static_cast<size_t>(offset) < kBufferSize) { get_offset_ = offset; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 92abfc0..a57df77 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -431,6 +431,11 @@ class GLES2DecoderTestBase : public testing::Test { DCHECK(false); } + virtual bool SetGetBuffer(int32 /* transfer_buffer_id */) OVERRIDE { + DCHECK(false); + return false; + } + // Overridden from CommandBufferEngine. virtual bool SetGetOffset(int32 offset) OVERRIDE { DCHECK(false); diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index f37c1a0..468f817 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -29,21 +29,6 @@ GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, decoder_(decoder), parser_(parser), unscheduled_count_(0) { - // Map the ring buffer and create the parser. - if (!parser) { - Buffer ring_buffer = command_buffer_->GetRingBuffer(); - if (ring_buffer.ptr) { - parser_.reset(new CommandParser(ring_buffer.ptr, - ring_buffer.size, - 0, - ring_buffer.size, - 0, - decoder_)); - } else { - parser_.reset(new CommandParser(NULL, 0, 0, 0, 0, - decoder_)); - } - } } GpuScheduler::~GpuScheduler() { @@ -150,6 +135,29 @@ void GpuScheduler::set_token(int32 token) { command_buffer_->SetToken(token); } +bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) { + // NOTE: This seems kind of strange. We need to update both the parser + // AND the command buffer. + Buffer ring_buffer = command_buffer_->GetTransferBuffer(transfer_buffer_id); + if (!ring_buffer.ptr) { + return false; + } + + if (!parser_.get()) { + parser_.reset(new CommandParser(decoder_)); + } + + parser_->SetBuffer( + ring_buffer.ptr, + ring_buffer.size, + 0, + ring_buffer.size); + + command_buffer_->SetGetBuffer(transfer_buffer_id); + SetGetOffset(0); + return true; +} + bool GpuScheduler::SetGetOffset(int32 offset) { if (parser_->set_get(offset)) { command_buffer_->SetGetOffset(static_cast<int32>(parser_->get())); diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 5256e49..9b7d9cd 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -51,6 +51,7 @@ class GpuScheduler // Implementation of CommandBufferEngine. virtual Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE; virtual void set_token(int32 token) OVERRIDE; + virtual bool SetGetBuffer(int32 transfer_buffer_id) OVERRIDE; virtual bool SetGetOffset(int32 offset) OVERRIDE; virtual int32 GetGetOffset() OVERRIDE; diff --git a/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/gpu/command_buffer/service/gpu_scheduler_unittest.cc index 2d230ec..e9d64c8 100644 --- a/gpu/command_buffer/service/gpu_scheduler_unittest.cc +++ b/gpu/command_buffer/service/gpu_scheduler_unittest.cc @@ -30,6 +30,8 @@ const size_t kRingBufferEntries = kRingBufferSize / sizeof(CommandBufferEntry); class GpuSchedulerTest : public testing::Test { protected: + static const int32 kTransferBufferId = 123; + virtual void SetUp() { shared_memory_.reset(new ::base::SharedMemory); shared_memory_->CreateAndMapAnonymous(kRingBufferSize); @@ -39,28 +41,21 @@ class GpuSchedulerTest : public testing::Test { memset(buffer_, 0, kRingBufferSize); command_buffer_.reset(new MockCommandBuffer); - ON_CALL(*command_buffer_.get(), GetRingBuffer()) - .WillByDefault(Return(shared_memory_buffer_)); CommandBuffer::State default_state; default_state.num_entries = kRingBufferEntries; ON_CALL(*command_buffer_.get(), GetState()) .WillByDefault(Return(default_state)); - async_api_.reset(new StrictMock<AsyncAPIMock>); - decoder_.reset(new gles2::MockGLES2Decoder()); - - parser_ = new CommandParser(buffer_, - kRingBufferEntries, - 0, - kRingBufferEntries, - 0, - async_api_.get()); - scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(), decoder_.get(), - parser_)); + NULL)); + EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId)) + .WillOnce(Return(shared_memory_buffer_)); + EXPECT_CALL(*command_buffer_, SetGetBuffer(kTransferBufferId)); + EXPECT_CALL(*command_buffer_, SetGetOffset(0)); + EXPECT_TRUE(scheduler_->SetGetBuffer(kTransferBufferId)); } virtual void TearDown() { @@ -82,8 +77,6 @@ class GpuSchedulerTest : public testing::Test { Buffer shared_memory_buffer_; int32* buffer_; scoped_ptr<gles2::MockGLES2Decoder> decoder_; - CommandParser* parser_; - scoped_ptr<AsyncAPIMock> async_api_; scoped_ptr<GpuScheduler> scheduler_; }; @@ -100,6 +93,25 @@ TEST_F(GpuSchedulerTest, SchedulerDoesNothingIfRingBufferIsEmpty) { scheduler_->PutChanged(); } +TEST_F(GpuSchedulerTest, GetSetBuffer) { + CommandBuffer::State state; + + // Set the get offset to something not 0. + EXPECT_CALL(*command_buffer_, SetGetOffset(2)); + scheduler_->SetGetOffset(2); + EXPECT_EQ(2, scheduler_->GetGetOffset()); + + // Set the buffer. + EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId)) + .WillOnce(Return(shared_memory_buffer_)); + EXPECT_CALL(*command_buffer_, SetGetBuffer(kTransferBufferId)); + EXPECT_CALL(*command_buffer_, SetGetOffset(0)); + EXPECT_TRUE(scheduler_->SetGetBuffer(kTransferBufferId)); + + // Check the get offset was reset. + EXPECT_EQ(0, scheduler_->GetGetOffset()); +} + TEST_F(GpuSchedulerTest, ProcessesOneCommand) { CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]); header[0].command = 7; @@ -113,7 +125,7 @@ TEST_F(GpuSchedulerTest, ProcessesOneCommand) { .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(2)); - EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) + EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0])) .WillOnce(Return(error::kNoError)); EXPECT_CALL(*command_buffer_, SetParseError(_)) @@ -136,11 +148,11 @@ TEST_F(GpuSchedulerTest, ProcessesTwoCommands) { EXPECT_CALL(*command_buffer_, GetState()) .WillRepeatedly(Return(state)); - EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) + EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0])) .WillOnce(Return(error::kNoError)); EXPECT_CALL(*command_buffer_, SetGetOffset(2)); - EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2])) + EXPECT_CALL(*decoder_, DoCommand(8, 0, &buffer_[2])) .WillOnce(Return(error::kNoError)); EXPECT_CALL(*command_buffer_, SetGetOffset(3)); @@ -158,11 +170,12 @@ TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) { EXPECT_CALL(*command_buffer_, GetState()) .WillRepeatedly(Return(state)); - EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) + EXPECT_CALL(*decoder_, DoCommand(7, 0, &buffer_[0])) .WillOnce(Return( error::kUnknownCommand)); EXPECT_CALL(*command_buffer_, SetGetOffset(1)); + EXPECT_CALL(*command_buffer_, SetContextLostReason(_)); EXPECT_CALL(*decoder_, GetContextLostReason()) .WillOnce(Return(error::kUnknown)); EXPECT_CALL(*command_buffer_, |