summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer')
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper.cc2
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper_test.cc2
-rw-r--r--gpu/command_buffer/client/fenced_allocator_test.cc2
-rw-r--r--gpu/command_buffer/client/gles2_demo.cc2
-rw-r--r--gpu/command_buffer/client/gles2_implementation_unittest.cc2
-rw-r--r--gpu/command_buffer/client/mapped_memory_unittest.cc2
-rw-r--r--gpu/command_buffer/client/ring_buffer_test.cc2
-rw-r--r--gpu/command_buffer/common/command_buffer.h17
-rw-r--r--gpu/command_buffer/common/command_buffer_mock.h2
-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
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) {