diff options
Diffstat (limited to 'gpu/command_buffer/service')
-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 |
6 files changed, 59 insertions, 40 deletions
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) { |