diff options
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper_test.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/fenced_allocator_test.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_demo.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_unittest.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/mapped_memory_unittest.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/ring_buffer_test.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/common/command_buffer.h | 17 | ||||
-rw-r--r-- | gpu/command_buffer/common/command_buffer_mock.h | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/command_buffer_service.cc | 20 | ||||
-rw-r--r-- | gpu/command_buffer/service/command_buffer_service.h | 25 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler.h | 11 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler_mock.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_scheduler_unittest.cc | 30 |
15 files changed, 79 insertions, 53 deletions
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 8da55b69..1054055 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -49,7 +49,7 @@ CommandBufferHelper::~CommandBufferHelper() { bool CommandBufferHelper::FlushSync() { last_put_sent_ = put_; - CommandBuffer::State state = command_buffer_->FlushSync(put_); + CommandBuffer::State state = command_buffer_->FlushSync(put_, get_); SynchronizeState(state); return state.error == error::kNoError; } diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 1daa942..56eaa0a 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -80,7 +80,7 @@ class CommandBufferHelperTest : public testing::Test { gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_, 1)); command_buffer_->SetPutOffsetChangeCallback(NewCallback( - gpu_scheduler_.get(), &GpuScheduler::ProcessCommands)); + gpu_scheduler_.get(), &GpuScheduler::PutChanged)); api_mock_->set_engine(gpu_scheduler_.get()); diff --git a/gpu/command_buffer/client/fenced_allocator_test.cc b/gpu/command_buffer/client/fenced_allocator_test.cc index 533e867..3bf9bd8 100644 --- a/gpu/command_buffer/client/fenced_allocator_test.cc +++ b/gpu/command_buffer/client/fenced_allocator_test.cc @@ -54,7 +54,7 @@ class BaseFencedAllocatorTest : public testing::Test { gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_, INT_MAX)); command_buffer_->SetPutOffsetChangeCallback(NewCallback( - gpu_scheduler_.get(), &GpuScheduler::ProcessCommands)); + gpu_scheduler_.get(), &GpuScheduler::PutChanged)); api_mock_->set_engine(gpu_scheduler_.get()); diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 096a9d3..54a3b89 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -68,7 +68,7 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) { } command_buffer->SetPutOffsetChangeCallback( - NewCallback(gpu_scheduler, &GpuScheduler::ProcessCommands)); + NewCallback(gpu_scheduler, &GpuScheduler::PutChanged)); GLES2CmdHelper* helper = new GLES2CmdHelper(command_buffer.get()); if (!helper->Initialize(size)) { diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 5665b96..68f2e6b 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -50,7 +50,7 @@ class GLES2MockCommandBufferHelper : public CommandBuffer { state_.put_offset = put_offset; } - virtual State FlushSync(int32 put_offset) { + 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); diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc index 93e63e7..067c8e6 100644 --- a/gpu/command_buffer/client/mapped_memory_unittest.cc +++ b/gpu/command_buffer/client/mapped_memory_unittest.cc @@ -52,7 +52,7 @@ class MappedMemoryTestBase : public testing::Test { gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_, INT_MAX)); command_buffer_->SetPutOffsetChangeCallback(NewCallback( - gpu_scheduler_.get(), &GpuScheduler::ProcessCommands)); + gpu_scheduler_.get(), &GpuScheduler::PutChanged)); api_mock_->set_engine(gpu_scheduler_.get()); diff --git a/gpu/command_buffer/client/ring_buffer_test.cc b/gpu/command_buffer/client/ring_buffer_test.cc index e3c14c7..1ccd979 100644 --- a/gpu/command_buffer/client/ring_buffer_test.cc +++ b/gpu/command_buffer/client/ring_buffer_test.cc @@ -55,7 +55,7 @@ class BaseRingBufferTest : public testing::Test { gpu_scheduler_.reset(new GpuScheduler( command_buffer_.get(), NULL, parser_, INT_MAX)); command_buffer_->SetPutOffsetChangeCallback(NewCallback( - gpu_scheduler_.get(), &GpuScheduler::ProcessCommands)); + gpu_scheduler_.get(), &GpuScheduler::PutChanged)); api_mock_->set_engine(gpu_scheduler_.get()); diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h index 4cbcef1..d438f72 100644 --- a/gpu/command_buffer/common/command_buffer.h +++ b/gpu/command_buffer/common/command_buffer.h @@ -27,7 +27,8 @@ class CommandBuffer { get_offset(0), put_offset(0), token(-1), - error(error::kNoError) { + error(error::kNoError), + generation(0) { } // Size of the command buffer in command buffer entries. @@ -48,6 +49,11 @@ class CommandBuffer { // Error status. error::Error error; + + // Generation index of this state. The generation index is incremented every + // time a new state is retrieved from the command processor, so that + // consistency can be kept even if IPC messages are processed out-of-order. + uint32 generation; }; CommandBuffer() { @@ -75,10 +81,11 @@ class CommandBuffer { // The writer calls this to update its put offset. This function returns the // reader's most recent get offset. Does not return until after the put offset // change callback has been invoked. Returns -1 if the put offset is invalid. - // As opposed to Flush(), this function guarantees that the reader has - // processed some commands before returning (assuming the command buffer isn't - // empty and there is no error). - virtual State FlushSync(int32 put_offset) = 0; + // If last_known_get is different from the reader's current get pointer, this + // function will return immediately, otherwise it guarantees that the reader + // has processed some commands before returning (assuming the command buffer + // isn't empty and there is no error). + virtual State FlushSync(int32 put_offset, int32 last_known_get) = 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.h b/gpu/command_buffer/common/command_buffer_mock.h index 8281f7f..4da8e82 100644 --- a/gpu/command_buffer/common/command_buffer_mock.h +++ b/gpu/command_buffer/common/command_buffer_mock.h @@ -26,7 +26,7 @@ class MockCommandBuffer : public CommandBuffer { MOCK_METHOD0(GetRingBuffer, Buffer()); MOCK_METHOD0(GetState, State()); MOCK_METHOD1(Flush, void(int32 put_offset)); - MOCK_METHOD1(FlushSync, State(int32 put_offset)); + MOCK_METHOD2(FlushSync, State(int32 put_offset, int32 last_known_get)); 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/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc index 86453eb..bc36fa3 100644 --- a/gpu/command_buffer/service/command_buffer_service.cc +++ b/gpu/command_buffer/service/command_buffer_service.cc @@ -19,6 +19,7 @@ CommandBufferService::CommandBufferService() get_offset_(0), put_offset_(0), token_(0), + generation_(0), error_(error::kNoError) { // Element zero is always NULL. registered_objects_.push_back(Buffer()); @@ -97,11 +98,13 @@ CommandBufferService::State CommandBufferService::GetState() { state.put_offset = put_offset_; state.token = token_; state.error = error_; + state.generation = ++generation_; return state; } -CommandBufferService::State CommandBufferService::FlushSync(int32 put_offset) { +CommandBufferService::State CommandBufferService::FlushSync( + int32 put_offset, int32 last_known_get) { if (put_offset < 0 || put_offset > num_entries_) { error_ = gpu::error::kOutOfBounds; return GetState(); @@ -110,14 +113,23 @@ CommandBufferService::State CommandBufferService::FlushSync(int32 put_offset) { put_offset_ = put_offset; if (put_offset_change_callback_.get()) { - put_offset_change_callback_->Run(); + put_offset_change_callback_->Run(last_known_get == get_offset_); } return GetState(); } void CommandBufferService::Flush(int32 put_offset) { - FlushSync(put_offset); + if (put_offset < 0 || put_offset > num_entries_) { + error_ = gpu::error::kOutOfBounds; + return; + } + + put_offset_ = put_offset; + + if (put_offset_change_callback_.get()) { + put_offset_change_callback_->Run(false); + } } void CommandBufferService::SetGetOffset(int32 get_offset) { @@ -241,7 +253,7 @@ void CommandBufferService::SetParseError(error::Error error) { } void CommandBufferService::SetPutOffsetChangeCallback( - Callback0::Type* callback) { + Callback1<bool>::Type* callback) { put_offset_change_callback_.reset(callback); } diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h index a83a4e5..a9bc9dfc 100644 --- a/gpu/command_buffer/service/command_buffer_service.h +++ b/gpu/command_buffer/service/command_buffer_service.h @@ -30,7 +30,7 @@ class CommandBufferService : public CommandBuffer { virtual Buffer GetRingBuffer(); virtual State GetState(); virtual void Flush(int32 put_offset); - virtual State FlushSync(int32 put_offset); + virtual State FlushSync(int32 put_offset, int32 last_known_get); virtual void SetGetOffset(int32 get_offset); virtual int32 CreateTransferBuffer(size_t size, int32 id_request); virtual int32 RegisterTransferBuffer(base::SharedMemory* shared_memory, @@ -41,27 +41,26 @@ class CommandBufferService : public CommandBuffer { virtual void SetToken(int32 token); virtual void SetParseError(error::Error error); - // Sets a callback that should be posted on another thread whenever the put - // offset is changed. The callback must not return until some progress has - // been made (unless the command buffer is empty), i.e. the - // get offset must have changed. It need not process the entire command - // buffer though. This allows concurrency between the writer and the reader - // while giving the writer a means of waiting for the reader to make some - // progress before attempting to write more to the command buffer. Avoiding - // the use of a synchronization primitive like a condition variable to - // synchronize reader and writer reduces the risk of deadlock. - // Takes ownership of callback. The callback is invoked on the plugin thread. - virtual void SetPutOffsetChangeCallback(Callback0::Type* callback); + // Sets a callback that is called whenever the put offset is changed. When + // called with sync==true, the callback must not return until some progress + // has been made (unless the command buffer is empty), i.e. the get offset + // must have changed. It need not process the entire command buffer though. + // This allows concurrency between the writer and the reader while giving the + // writer a means of waiting for the reader to make some progress before + // attempting to write more to the command buffer. Takes ownership of + // callback. + virtual void SetPutOffsetChangeCallback(Callback1<bool>::Type* callback); private: Buffer ring_buffer_; int32 num_entries_; int32 get_offset_; int32 put_offset_; - scoped_ptr<Callback0::Type> put_offset_change_callback_; + scoped_ptr<Callback1<bool>::Type> put_offset_change_callback_; std::vector<Buffer> registered_objects_; std::set<int32> unused_registered_object_elements_; int32 token_; + uint32 generation_; error::Error error_; }; diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc index be47663..c1b7aaa 100644 --- a/gpu/command_buffer/service/gpu_scheduler.cc +++ b/gpu/command_buffer/service/gpu_scheduler.cc @@ -117,6 +117,16 @@ const unsigned int kMaxOutstandingSwapBuffersCallsPerOnscreenContext = 1; } #endif +void GpuScheduler::PutChanged(bool sync) { + CommandBuffer::State state = command_buffer_->GetState(); + parser_->set_put(state.put_offset); + + if (sync) + ProcessCommands(); + else + ScheduleProcessCommands(); +} + void GpuScheduler::ProcessCommands() { GPU_TRACE_EVENT0("gpu", "GpuScheduler:ProcessCommands"); CommandBuffer::State state = command_buffer_->GetState(); @@ -134,8 +144,6 @@ void GpuScheduler::ProcessCommands() { } } - parser_->set_put(state.put_offset); - #if defined(OS_MACOSX) bool do_rate_limiting = surface_.get() != NULL; // Don't swamp the browser process with SwapBuffers calls it can't handle. diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h index 04784a7..ebb2368 100644 --- a/gpu/command_buffer/service/gpu_scheduler.h +++ b/gpu/command_buffer/service/gpu_scheduler.h @@ -61,7 +61,7 @@ class GpuScheduler : public CommandBufferEngine { void Destroy(); void DestroyCommon(); - virtual void ProcessCommands(); + void PutChanged(bool sync); // Sets whether commands should be processed by this scheduler. Setting to // false unschedules. Setting to true reschedules. Whether or not the @@ -108,14 +108,14 @@ class GpuScheduler : public CommandBufferEngine { // Sets a callback that is called when a glResizeCHROMIUM command // is processed. - virtual void SetResizeCallback(Callback1<gfx::Size>::Type* callback); + void SetResizeCallback(Callback1<gfx::Size>::Type* callback); // Sets a callback which is called when a SwapBuffers command is processed. // Must be called after Initialize(). // It is not defined on which thread this callback is called. - virtual void SetSwapBuffersCallback(Callback0::Type* callback); + void SetSwapBuffersCallback(Callback0::Type* callback); - virtual void SetCommandProcessedCallback(Callback0::Type* callback); + void SetCommandProcessedCallback(Callback0::Type* callback); // Sets a callback which is called after a Set/WaitLatch command is processed. // The bool parameter will be true for SetLatch, and false for a WaitLatch @@ -145,7 +145,8 @@ class GpuScheduler : public CommandBufferEngine { // Called via a callback just before we are supposed to call the // user's swap buffers callback. - virtual void WillSwapBuffers(); + void WillSwapBuffers(); + void ProcessCommands(); // The GpuScheduler holds a weak reference to the CommandBuffer. The // CommandBuffer owns the GpuScheduler and holds a strong reference to it diff --git a/gpu/command_buffer/service/gpu_scheduler_mock.h b/gpu/command_buffer/service/gpu_scheduler_mock.h index 4bc1bb5..ed308e0 100644 --- a/gpu/command_buffer/service/gpu_scheduler_mock.h +++ b/gpu/command_buffer/service/gpu_scheduler_mock.h @@ -16,7 +16,6 @@ class MockGpuScheduler : public GpuScheduler { : GpuScheduler(command_buffer) { } - MOCK_METHOD0(ProcessCommands, void()); MOCK_METHOD1(GetSharedMemoryBuffer, Buffer(int32 shm_id)); MOCK_METHOD1(set_token, void(int32 token)); diff --git a/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/gpu/command_buffer/service/gpu_scheduler_unittest.cc index b992fa7..a7f17b9 100644 --- a/gpu/command_buffer/service/gpu_scheduler_unittest.cc +++ b/gpu/command_buffer/service/gpu_scheduler_unittest.cc @@ -92,13 +92,13 @@ TEST_F(GpuSchedulerTest, SchedulerDoesNothingIfRingBufferIsEmpty) { state.put_offset = 0; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(0)); EXPECT_CALL(*command_buffer_, SetParseError(_)) .Times(0); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, ProcessesOneCommand) { @@ -111,7 +111,7 @@ TEST_F(GpuSchedulerTest, ProcessesOneCommand) { state.put_offset = 2; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(2)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) @@ -120,7 +120,7 @@ TEST_F(GpuSchedulerTest, ProcessesOneCommand) { EXPECT_CALL(*command_buffer_, SetParseError(_)) .Times(0); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, ProcessesTwoCommands) { @@ -135,7 +135,7 @@ TEST_F(GpuSchedulerTest, ProcessesTwoCommands) { state.put_offset = 3; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(3)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) @@ -144,7 +144,7 @@ TEST_F(GpuSchedulerTest, ProcessesTwoCommands) { EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2])) .WillOnce(Return(error::kNoError)); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, SchedulerSetsTheGLContext) { @@ -155,11 +155,11 @@ TEST_F(GpuSchedulerTest, SchedulerSetsTheGLContext) { CommandBuffer::State state; state.put_offset = 0; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*command_buffer_, SetGetOffset(0)); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, PostsTaskToFinishRemainingCommands) { @@ -176,7 +176,7 @@ TEST_F(GpuSchedulerTest, PostsTaskToFinishRemainingCommands) { state.put_offset = 4; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0])) .WillOnce(Return(error::kNoError)); @@ -186,13 +186,13 @@ TEST_F(GpuSchedulerTest, PostsTaskToFinishRemainingCommands) { EXPECT_CALL(*command_buffer_, SetGetOffset(3)); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); // ProcessCommands is called a second time when the pending task is run. state.put_offset = 4; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3])) .WillOnce(Return(error::kNoError)); @@ -211,7 +211,7 @@ TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) { state.put_offset = 1; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0])) .WillOnce(Return( @@ -220,7 +220,7 @@ TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) { EXPECT_CALL(*command_buffer_, SetParseError(error::kUnknownCommand)); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, ProcessCommandsDoesNothingAfterError) { @@ -228,9 +228,9 @@ TEST_F(GpuSchedulerTest, ProcessCommandsDoesNothingAfterError) { state.error = error::kGenericError; EXPECT_CALL(*command_buffer_, GetState()) - .WillOnce(Return(state)); + .WillRepeatedly(Return(state)); - scheduler_->ProcessCommands(); + scheduler_->PutChanged(true); } TEST_F(GpuSchedulerTest, CanGetAddressOfSharedMemory) { |