diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-15 05:37:57 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-15 05:37:57 +0000 |
commit | 617296e34da57fd9357acdc57f825144d8daa688 (patch) | |
tree | ae9462c2762ab328f86302e8d35d7c8f66448722 /gpu | |
parent | e1549a0ad266ca2377fffb02a7f2017717ac3c94 (diff) | |
download | chromium_src-617296e34da57fd9357acdc57f825144d8daa688.zip chromium_src-617296e34da57fd9357acdc57f825144d8daa688.tar.gz chromium_src-617296e34da57fd9357acdc57f825144d8daa688.tar.bz2 |
Free the command buffer when tabs are switched
GLES2Implemetation::FreeEverything now fress everything it can.
the transfer buffer, the command buffer and any unused mapped
buffer (glMapSubXXX).
BUG=103989
TEST=unit tests
Review URL: http://codereview.chromium.org/8953006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114602 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.cc | 22 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper_test.cc | 68 | ||||
-rw-r--r-- | gpu/command_buffer/client/fenced_allocator_test.cc | 13 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 1 | ||||
-rw-r--r-- | gpu/command_buffer/client/mapped_memory_unittest.cc | 13 | ||||
-rw-r--r-- | gpu/command_buffer/client/ring_buffer_test.cc | 23 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.h | 13 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler_unittest.cc | 4 |
10 files changed, 110 insertions, 65 deletions
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index d43efc3..22af6db 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -30,6 +30,10 @@ CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) } bool CommandBufferHelper::AllocateRingBuffer() { + if (HaveRingBuffer()) { + return true; + } + int32 id = command_buffer_->CreateTransferBuffer(ring_buffer_size_, -1); if (id < 0) { return false; @@ -61,6 +65,14 @@ bool CommandBufferHelper::AllocateRingBuffer() { return true; } +void CommandBufferHelper::FreeRingBuffer() { + GPU_CHECK_EQ(put_, get_offset()); + if (HaveRingBuffer()) { + command_buffer_->DestroyTransferBuffer(ring_buffer_id_); + ring_buffer_id_ = -1; + } +} + bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { ring_buffer_size_ = ring_buffer_size; return AllocateRingBuffer(); @@ -70,6 +82,7 @@ CommandBufferHelper::~CommandBufferHelper() { } bool CommandBufferHelper::FlushSync() { + GPU_DCHECK(HaveRingBuffer()); last_flush_time_ = clock(); last_put_sent_ = put_; CommandBuffer::State state = command_buffer_->FlushSync(put_, get_offset()); @@ -77,6 +90,7 @@ bool CommandBufferHelper::FlushSync() { } void CommandBufferHelper::Flush() { + GPU_DCHECK(HaveRingBuffer()); last_flush_time_ = clock(); last_put_sent_ = put_; command_buffer_->Flush(put_); @@ -86,6 +100,7 @@ void CommandBufferHelper::Flush() { // error is set. bool CommandBufferHelper::Finish() { TRACE_EVENT0("gpu", "CommandBufferHelper::Finish"); + GPU_DCHECK(HaveRingBuffer()); do { // Do not loop forever if the flush fails, meaning the command buffer reader // has shutdown. @@ -101,6 +116,8 @@ bool CommandBufferHelper::Finish() { // value is higher than that token). Calls Finish() if the token value wraps, // which will be rare. int32 CommandBufferHelper::InsertToken() { + AllocateRingBuffer(); + GPU_DCHECK(HaveRingBuffer()); // Increment token as 31-bit integer. Negative values are used to signal an // error. token_ = (token_ + 1) & 0x7FFFFFFF; @@ -118,6 +135,7 @@ int32 CommandBufferHelper::InsertToken() { // Waits until the current token value is greater or equal to the value passed // in argument. void CommandBufferHelper::WaitForToken(int32 token) { + GPU_DCHECK(HaveRingBuffer()); TRACE_EVENT_IF_LONGER_THAN0(50, "gpu", "CommandBufferHelper::WaitForToken"); // Return immediately if corresponding InsertToken failed. if (token < 0) @@ -141,6 +159,8 @@ void CommandBufferHelper::WaitForToken(int32 token) { // function will return early if an error occurs, in which case the available // space may not be available. void CommandBufferHelper::WaitForAvailableEntries(int32 count) { + AllocateRingBuffer(); + GPU_DCHECK(HaveRingBuffer()); GPU_DCHECK(count < usable_entry_count_); if (put_ + count > usable_entry_count_) { // There's not enough room between the current put and the end of the @@ -188,6 +208,8 @@ void CommandBufferHelper::WaitForAvailableEntries(int32 count) { } CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { + AllocateRingBuffer(); + GPU_DCHECK(HaveRingBuffer()); ++commands_issued_; WaitForAvailableEntries(entries); CommandBufferEntry* space = &entries_[put_]; diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h index 5fbf462..d27b25f 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -218,6 +218,12 @@ class CommandBufferHelper { return ring_buffer_; } + void FreeRingBuffer(); + + bool HaveRingBuffer() const { + return ring_buffer_id_ != -1; + } + private: // Waits until get changes, updating the value of get_. void WaitForGetChange(); diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 216bb60..2fa1fee 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -41,8 +41,8 @@ class CommandBufferHelperTest : public testing::Test { // Helper so mock can handle the Jump command. class DoJumpCommand { public: - explicit DoJumpCommand(CommandParser* parser) - : parser_(parser) { + explicit DoJumpCommand(GpuScheduler* gpu_scheduler) + : gpu_scheduler_(gpu_scheduler) { } error::Error DoCommand( @@ -50,12 +50,12 @@ class CommandBufferHelperTest : public testing::Test { unsigned int arg_count, const void* cmd_data) { const cmd::Jump* jump_cmd = static_cast<const cmd::Jump*>(cmd_data); - parser_->set_get(jump_cmd->offset); + gpu_scheduler_->parser()->set_get(jump_cmd->offset); return error::kNoError; }; private: - CommandParser* parser_; + GpuScheduler* gpu_scheduler_; }; virtual void SetUp() { @@ -68,28 +68,23 @@ class CommandBufferHelperTest : public testing::Test { command_buffer_.reset(new CommandBufferService); command_buffer_->Initialize(); - parser_ = new CommandParser(api_mock_.get()); + gpu_scheduler_.reset(new GpuScheduler( + command_buffer_.get(), api_mock_.get(), NULL)); + command_buffer_->SetPutOffsetChangeCallback(base::Bind( + &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); + command_buffer_->SetGetBufferChangeCallback(base::Bind( + &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); - do_jump_command_.reset(new DoJumpCommand(parser_)); + do_jump_command_.reset(new DoJumpCommand(gpu_scheduler_.get())); EXPECT_CALL(*api_mock_, DoCommand(cmd::kJump, _, _)) .WillRepeatedly( Invoke(do_jump_command_.get(), &DoJumpCommand::DoCommand)); - gpu_scheduler_.reset(new GpuScheduler( - command_buffer_.get(), NULL, parser_)); - command_buffer_->SetPutOffsetChangeCallback(base::Bind( - &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); api_mock_->set_engine(gpu_scheduler_.get()); 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() { @@ -97,6 +92,10 @@ class CommandBufferHelperTest : public testing::Test { MessageLoop::current()->RunAllPending(); } + const CommandParser* GetParser() const { + return gpu_scheduler_->parser(); + } + // Adds a command to the buffer through the helper, while adding it as an // expected call on the API mock. void AddCommandWithExpect(error::Error _return, @@ -121,8 +120,8 @@ class CommandBufferHelperTest : public testing::Test { // Checks that the buffer from put to put+size is free in the parser. void CheckFreeSpace(CommandBufferOffset put, unsigned int size) { - CommandBufferOffset parser_put = parser_->put(); - CommandBufferOffset parser_get = parser_->get(); + CommandBufferOffset parser_put = GetParser()->put(); + CommandBufferOffset parser_get = GetParser()->get(); CommandBufferOffset limit = put + size; if (parser_get > parser_put) { // "busy" buffer wraps, so "free" buffer is between put (inclusive) and @@ -163,7 +162,6 @@ class CommandBufferHelperTest : public testing::Test { scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; - CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; Sequence sequence_; scoped_ptr<DoJumpCommand> do_jump_command_; @@ -174,7 +172,7 @@ class CommandBufferHelperTest : public testing::Test { TEST_F(CommandBufferHelperTest, TestCommandProcessing) { // Check initial state of the engine - it should have been configured by the // helper. - EXPECT_TRUE(parser_ != NULL); + EXPECT_TRUE(GetParser() != NULL); EXPECT_EQ(error::kNoError, GetError()); EXPECT_EQ(0, GetGetOffset()); @@ -194,7 +192,7 @@ TEST_F(CommandBufferHelperTest, TestCommandProcessing) { // Wait until it's done. helper_->Finish(); // Check that the engine has no more work to do. - EXPECT_TRUE(parser_->IsEmpty()); + EXPECT_TRUE(GetParser()->IsEmpty()); // Check that the commands did happen. Mock::VerifyAndClearExpectations(api_mock_.get()); @@ -309,4 +307,32 @@ TEST_F(CommandBufferHelperTest, TestToken) { EXPECT_EQ(error::kNoError, GetError()); } +TEST_F(CommandBufferHelperTest, FreeRingBuffer) { + EXPECT_TRUE(helper_->HaveRingBuffer()); + + // Test freeing ring buffer. + helper_->FreeRingBuffer(); + EXPECT_FALSE(helper_->HaveRingBuffer()); + + // Test that InsertToken allocates a new one + int32 token = helper_->InsertToken(); + EXPECT_TRUE(helper_->HaveRingBuffer()); + EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _)) + .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken), + Return(error::kNoError))); + helper_->WaitForToken(token); + helper_->FreeRingBuffer(); + EXPECT_FALSE(helper_->HaveRingBuffer()); + + // Test that WaitForAvailableEntries allocates a new one + AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL); + EXPECT_TRUE(helper_->HaveRingBuffer()); + helper_->Finish(); + helper_->FreeRingBuffer(); + EXPECT_FALSE(helper_->HaveRingBuffer()); + + // Check that the commands did happen. + Mock::VerifyAndClearExpectations(api_mock_.get()); +} + } // namespace gpu diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc index ebd8ff6..731f374 100644 --- a/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/gpu/command_buffer/client/fenced_allocator_test.cc @@ -47,23 +47,17 @@ class BaseFencedAllocatorTest : public testing::Test { command_buffer_.reset(new CommandBufferService); command_buffer_->Initialize(); - parser_ = new CommandParser(api_mock_.get()); - gpu_scheduler_.reset(new GpuScheduler( - command_buffer_.get(), NULL, parser_)); + command_buffer_.get(), api_mock_.get(), NULL)); command_buffer_->SetPutOffsetChangeCallback(base::Bind( &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); + command_buffer_->SetGetBufferChangeCallback(base::Bind( + &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); api_mock_->set_engine(gpu_scheduler_.get()); 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() { @@ -77,7 +71,6 @@ class BaseFencedAllocatorTest : public testing::Test { scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; - CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; }; diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 15f6bfb..ecf4d6c 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -737,6 +737,7 @@ void GLES2Implementation::FreeEverything() { Finish(); FreeUnusedSharedMemory(); transfer_buffer_.Free(); + helper_->FreeRingBuffer(); } void GLES2Implementation::WaitForCmd() { diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc index c18ec9f..4442d88 100644 --- a/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -44,23 +44,17 @@ class MappedMemoryTestBase : public testing::Test { command_buffer_.reset(new CommandBufferService); command_buffer_->Initialize(); - parser_ = new CommandParser(api_mock_.get()); - gpu_scheduler_.reset(new GpuScheduler( - command_buffer_.get(), NULL, parser_)); + command_buffer_.get(), api_mock_.get(), NULL)); command_buffer_->SetPutOffsetChangeCallback(base::Bind( &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); + command_buffer_->SetGetBufferChangeCallback(base::Bind( + &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); api_mock_->set_engine(gpu_scheduler_.get()); 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() { @@ -74,7 +68,6 @@ class MappedMemoryTestBase : public testing::Test { scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; - CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; }; diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc index 8b8e46e..86dc020 100644 --- a/gpu/command_buffer/client/ring_buffer_test.cc +++ b/gpu/command_buffer/client/ring_buffer_test.cc @@ -36,8 +36,8 @@ class BaseRingBufferTest : public testing::Test { class DoJumpCommand { public: - explicit DoJumpCommand(CommandParser* parser) - : parser_(parser) { + explicit DoJumpCommand(GpuScheduler* gpu_scheduler) + : gpu_scheduler_(gpu_scheduler) { } error::Error DoCommand( @@ -45,12 +45,12 @@ class BaseRingBufferTest : public testing::Test { unsigned int arg_count, const void* cmd_data) { const cmd::Jump* jump_cmd = static_cast<const cmd::Jump*>(cmd_data); - parser_->set_get(jump_cmd->offset); + gpu_scheduler_->parser()->set_get(jump_cmd->offset); return error::kNoError; }; private: - CommandParser* parser_; + GpuScheduler* gpu_scheduler_; }; virtual void SetUp() { @@ -67,27 +67,21 @@ class BaseRingBufferTest : public testing::Test { command_buffer_.reset(new CommandBufferService); command_buffer_->Initialize(); - parser_ = new CommandParser(api_mock_.get()); - gpu_scheduler_.reset(new GpuScheduler( - command_buffer_.get(), NULL, parser_)); + command_buffer_.get(), api_mock_.get(), NULL)); command_buffer_->SetPutOffsetChangeCallback(base::Bind( &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); + command_buffer_->SetGetBufferChangeCallback(base::Bind( + &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); api_mock_->set_engine(gpu_scheduler_.get()); - do_jump_command_.reset(new DoJumpCommand(parser_)); + do_jump_command_.reset(new DoJumpCommand(gpu_scheduler_.get())); EXPECT_CALL(*api_mock_, DoCommand(cmd::kJump, _, _)) .WillRepeatedly( Invoke(do_jump_command_.get(), &DoJumpCommand::DoCommand)); 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() { @@ -101,7 +95,6 @@ class BaseRingBufferTest : public testing::Test { scoped_ptr<AsyncAPIMock> api_mock_; scoped_ptr<CommandBufferService> command_buffer_; scoped_ptr<GpuScheduler> gpu_scheduler_; - CommandParser* parser_; scoped_ptr<CommandBufferHelper> helper_; scoped_ptr<DoJumpCommand> do_jump_command_; }; diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index 9282e73..e294dcf 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -17,12 +17,14 @@ using ::base::SharedMemory; namespace gpu { -GpuScheduler::GpuScheduler(CommandBuffer* command_buffer, - gles2::GLES2Decoder* decoder, - CommandParser* parser) +GpuScheduler::GpuScheduler( + CommandBuffer* command_buffer, + AsyncAPIInterface* handler, + gles2::GLES2Decoder* decoder) : command_buffer_(command_buffer), + handler_(handler), decoder_(decoder), - parser_(parser), + parser_(NULL), unscheduled_count_(0) { } @@ -121,7 +123,7 @@ bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) { } if (!parser_.get()) { - parser_.reset(new CommandParser(decoder_)); + parser_.reset(new CommandParser(handler_)); } parser_->SetBuffer( diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index f7fd49e..3a33da4 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -28,8 +28,8 @@ class GpuScheduler public base::SupportsWeakPtr<GpuScheduler> { public: GpuScheduler(CommandBuffer* command_buffer, - gles2::GLES2Decoder* decoder, - CommandParser* parser); + AsyncAPIInterface* handler, + gles2::GLES2Decoder* decoder); virtual ~GpuScheduler(); @@ -62,6 +62,10 @@ class GpuScheduler void DeferToFence(base::Closure task); + CommandParser* parser() const { + return parser_.get(); + } + private: // Polls the fences, invoking callbacks that were waiting to be triggered // by them and returns whether all fences were complete. @@ -72,6 +76,9 @@ class GpuScheduler // through the ProcessCommands callback. CommandBuffer* command_buffer_; + // The parser uses this to execute commands. + AsyncAPIInterface* handler_; + // Does not own decoder. TODO(apatrick): The GpuScheduler shouldn't need a // pointer to the decoder, it is only used to initialize the CommandParser, // which could be an argument to the constructor, and to determine the @@ -98,6 +105,8 @@ class GpuScheduler base::Closure scheduled_callback_; base::Closure command_processed_callback_; + + DISALLOW_COPY_AND_ASSIGN(GpuScheduler); }; } // namespace gpu diff --git a/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/gpu/command_buffer/service/gpu_scheduler_unittest.cc index cf881e6..a8e3021 100644 --- a/gpu/command_buffer/service/gpu_scheduler_unittest.cc +++ b/gpu/command_buffer/service/gpu_scheduler_unittest.cc @@ -45,12 +45,12 @@ class GpuSchedulerTest : public testing::Test { CommandBuffer::State default_state; default_state.num_entries = kRingBufferEntries; ON_CALL(*command_buffer_.get(), GetState()) - .WillByDefault(Return(default_state)); + .WillByDefault(Return(default_state)); decoder_.reset(new gles2::MockGLES2Decoder()); scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(), decoder_.get(), - NULL)); + decoder_.get())); EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId)) .WillOnce(Return(shared_memory_buffer_)); EXPECT_CALL(*command_buffer_, SetGetOffset(0)); |