summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r--gpu/command_buffer/service/command_buffer_service.cc20
-rw-r--r--gpu/command_buffer/service/command_buffer_service.h25
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.cc12
-rw-r--r--gpu/command_buffer/service/gpu_scheduler.h11
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_mock.h1
-rw-r--r--gpu/command_buffer/service/gpu_scheduler_unittest.cc30
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) {