diff options
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.cc | 22 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.h | 43 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper_test.cc | 15 | ||||
-rw-r--r-- | gpu/command_buffer/common/cmd_buffer_common.h | 52 | ||||
-rw-r--r-- | gpu/command_buffer/service/cmd_buffer_engine.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/cmd_parser.cc | 2 | ||||
-rw-r--r-- | gpu/command_buffer/service/cmd_parser.h | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/common_decoder.cc | 36 | ||||
-rw-r--r-- | gpu/command_buffer/service/common_decoder.h | 16 | ||||
-rw-r--r-- | gpu/command_buffer/service/common_decoder_unittest.cc | 147 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor.cc | 12 | ||||
-rw-r--r-- | gpu/command_buffer/service/gpu_processor.h | 2 |
13 files changed, 265 insertions, 112 deletions
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index 45c0866..0651ee6 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -62,10 +62,8 @@ int32 CommandBufferHelper::InsertToken() { // Increment token as 31-bit integer. Negative values are used to signal an // error. token_ = (token_ + 1) & 0x7FFFFFFF; - CommandBufferEntry args; - args.value_uint32 = token_; - const uint32 kSetToken = 1; // TODO(gman): add a common set of commands. - AddCommand(kSetToken, 1, &args); + cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>(); + cmd.Init(token_); if (token_ == 0) { // we wrapped Finish(); @@ -118,15 +116,13 @@ void CommandBufferHelper::WaitForAvailableEntries(int32 count) { if (!Flush()) return; } - // Add the noops. By convention, a noop is a command 0 with no args. - // TODO(apatrick): A noop can have a size. It would be better to add a - // single noop with a variable size. Watch out for size limit on - // individual commands. - CommandHeader header; - header.size = 1; - header.command = 0; - while (put_ < entry_count_) { - entries_[put_++].value_header = header; + // Insert Noops to fill out buffer. + int32 num_entries = entry_count_ - put_; + while (num_entries > 0) { + int32 num_to_skip = std::min(CommandHeader::kMaxSize, num_entries); + cmd::Noop::Set(&entries_[put_], num_to_skip); + put_ += num_to_skip; + num_entries -= num_to_skip; } put_ = 0; } diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h index 6c134fa..df56e2e 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.h +++ b/gpu/command_buffer/client/cmd_buffer_helper.h @@ -55,49 +55,6 @@ class CommandBufferHelper { // the size of the buffer minus one. void WaitForAvailableEntries(int32 count); - // Adds a command data to the command buffer. This may wait until sufficient - // space is available. - // Parameters: - // entries: The command entries to add. - // count: The number of entries. - void AddCommandData(const CommandBufferEntry* entries, int32 count) { - WaitForAvailableEntries(count); - for (; count > 0; --count) { - entries_[put_++] = *entries++; - } - DCHECK_LE(put_, entry_count_); - if (put_ == entry_count_) put_ = 0; - } - - // A typed version of AddCommandData. - template <typename T> - void AddTypedCmdData(const T& cmd) { - AddCommandData(reinterpret_cast<const CommandBufferEntry*>(&cmd), - ComputeNumEntries(sizeof(cmd))); - } - - // Adds a command to the command buffer. This may wait until sufficient space - // is available. - // Parameters: - // command: the command index. - // arg_count: the number of arguments for the command. - // args: the arguments for the command (these are copied before the - // function returns). - void AddCommand(int32 command, - int32 arg_count, - const CommandBufferEntry *args) { - CommandHeader header; - header.size = arg_count + 1; - header.command = command; - WaitForAvailableEntries(header.size); - entries_[put_++].value_header = header; - for (int i = 0; i < arg_count; ++i) { - entries_[put_++] = args[i]; - } - DCHECK_LE(put_, entry_count_); - if (put_ == entry_count_) put_ = 0; - } - // Inserts a new token into the command buffer. This token either has a value // different from previously inserted tokens, or ensures that previously // inserted tokens with that value have already passed through the command diff --git a/gpu/command_buffer/client/cmd_buffer_helper_test.cc b/gpu/command_buffer/client/cmd_buffer_helper_test.cc index 6c8fa6c..96f7004 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper_test.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper_test.cc @@ -35,7 +35,7 @@ class CommandBufferHelperTest : public testing::Test { api_mock_.reset(new AsyncAPIMock); // ignore noops in the mock - we don't want to inspect the internals of the // helper. - EXPECT_CALL(*api_mock_, DoCommand(0, 0, _)) + EXPECT_CALL(*api_mock_, DoCommand(0, _, _)) .WillRepeatedly(Return(parse_error::kParseNoError)); command_buffer_.reset(new CommandBufferService); @@ -70,9 +70,18 @@ class CommandBufferHelperTest : public testing::Test { // expected call on the API mock. void AddCommandWithExpect(parse_error::ParseError _return, unsigned int command, - unsigned int arg_count, + int arg_count, CommandBufferEntry *args) { - helper_->AddCommand(command, arg_count, args); + CommandHeader header; + header.size = arg_count + 1; + header.command = command; + CommandBufferEntry* cmds = helper_->GetSpace(arg_count + 1); + CommandBufferOffset put = 0; + cmds[put++].value_header = header; + for (int ii = 0; ii < arg_count; ++ii) { + cmds[put++] = args[ii]; + } + EXPECT_CALL(*api_mock_, DoCommand(command, arg_count, Truly(AsyncAPIMock::IsArgs(arg_count, args)))) .InSequence(sequence_) diff --git a/gpu/command_buffer/common/cmd_buffer_common.h b/gpu/command_buffer/common/cmd_buffer_common.h index 85b4144..5b23620 100644 --- a/gpu/command_buffer/common/cmd_buffer_common.h +++ b/gpu/command_buffer/common/cmd_buffer_common.h @@ -38,8 +38,10 @@ struct CommandHeader { Uint32 size:21; Uint32 command:11; - void Init(uint32 _command, uint32 _size) { - DCHECK_LE(_size, 1u << 22); + static const int32 kMaxSize = (1 << 21) - 1; + + void Init(uint32 _command, int32 _size) { + DCHECK_LE(_size, kMaxSize); command = _command; size = _size; } @@ -180,7 +182,8 @@ struct Noop { static const cmd::ArgFlags kArgFlags = cmd::kAtLeastN; void SetHeader(uint32 skip_count) { - header.Init(kCmdId, skip_count + 1); + DCHECK_GT(skip_count, 0u); + header.Init(kCmdId, skip_count); } void Init(uint32 skip_count) { @@ -239,30 +242,25 @@ struct Jump { header.SetCmd<ValueType>(); } - void Init(uint32 _shared_memory_id, uint32 _shared_memory_offset) { + void Init(uint32 _offset) { SetHeader(); - shared_memory_id = _shared_memory_id; - shared_memory_offset = _shared_memory_offset; + offset = _offset; } static void* Set( - void* cmd, uint32 _shared_memory_id, uint32 _shared_memory_offset) { - static_cast<ValueType*>(cmd)->Init( - _shared_memory_id, _shared_memory_offset); + void* cmd, uint32 _offset) { + static_cast<ValueType*>(cmd)->Init(_offset); return NextCmdAddress<ValueType>(cmd); } CommandHeader header; - uint32 shared_memory_id; - uint32 shared_memory_offset; + uint32 offset; }; -COMPILE_ASSERT(sizeof(Jump) == 12, Sizeof_Jump_is_not_12); +COMPILE_ASSERT(sizeof(Jump) == 8, Sizeof_Jump_is_not_8); COMPILE_ASSERT(offsetof(Jump, header) == 0, Offsetof_Jump_header_not_0); -COMPILE_ASSERT(offsetof(Jump, shared_memory_id) == 4, - Offsetof_Jump_shared_memory_id_not_4); -COMPILE_ASSERT(offsetof(Jump, shared_memory_offset) == 8, - Offsetof_Jump_shared_memory_offset_not_8); +COMPILE_ASSERT(offsetof(Jump, offset) == 4, + Offsetof_Jump_offset_not_4); // The JumpRelative command jumps to another place in the command buffer // relative to the end of this command. In other words. JumpRelative with an @@ -306,30 +304,24 @@ struct Call { header.SetCmd<ValueType>(); } - void Init(uint32 _shared_memory_id, uint32 _shared_memory_offset) { + void Init(uint32 _offset) { SetHeader(); - shared_memory_id = _shared_memory_id; - shared_memory_offset = _shared_memory_offset; + offset = _offset; } - static void* Set( - void* cmd, uint32 _shared_memory_id, uint32 _shared_memory_offset) { - static_cast<ValueType*>(cmd)->Init( - _shared_memory_id, _shared_memory_offset); + static void* Set(void* cmd, uint32 _offset) { + static_cast<ValueType*>(cmd)->Init(_offset); return NextCmdAddress<ValueType>(cmd); } CommandHeader header; - uint32 shared_memory_id; - uint32 shared_memory_offset; + uint32 offset; }; -COMPILE_ASSERT(sizeof(Call) == 12, Sizeof_Call_is_not_12); +COMPILE_ASSERT(sizeof(Call) == 8, Sizeof_Call_is_not_8); COMPILE_ASSERT(offsetof(Call, header) == 0, Offsetof_Call_header_not_0); -COMPILE_ASSERT(offsetof(Call, shared_memory_id) == 4, - Offsetof_Call_shared_memory_id_not_4); -COMPILE_ASSERT(offsetof(Call, shared_memory_offset) == 8, - Offsetof_Call_shared_memory_offset_not_8); +COMPILE_ASSERT(offsetof(Call, offset) == 4, + Offsetof_Call_offset_not_4); // The CallRelative command jumps to a subroutine using a relative offset. The // offset is relative to the end of this command.. diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h index 09419a0..964944d 100644 --- a/gpu/command_buffer/service/cmd_buffer_engine.h +++ b/gpu/command_buffer/service/cmd_buffer_engine.h @@ -29,6 +29,12 @@ class CommandBufferEngine { // Sets the token value. virtual void set_token(int32 token) = 0; + // Sets the "get" pointer. Return false if offset is out of range. + virtual bool SetGetOffset(int32 offset) = 0; + + // Gets the "get" pointer. + virtual int32 GetGetOffset() = 0; + private: DISALLOW_COPY_AND_ASSIGN(CommandBufferEngine); }; diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc index abe6fed..885385b 100644 --- a/gpu/command_buffer/service/cmd_parser.cc +++ b/gpu/command_buffer/service/cmd_parser.cc @@ -46,7 +46,7 @@ parse_error::ParseError CommandParser::ProcessCommand() { return parse_error::kParseInvalidSize; } - if (static_cast<size_t>(header.size + get) > entry_count_) { + if (static_cast<int>(header.size) + get > entry_count_) { DLOG(INFO) << "Error: get offset out of bounds"; return parse_error::kParseOutOfBounds; } diff --git a/gpu/command_buffer/service/cmd_parser.h b/gpu/command_buffer/service/cmd_parser.h index 69e115d..ebffb01 100644 --- a/gpu/command_buffer/service/cmd_parser.h +++ b/gpu/command_buffer/service/cmd_parser.h @@ -29,6 +29,16 @@ class CommandParser { // buffer considered as an array of CommandBufferEntry. CommandBufferOffset get() const { return get_; } + // Sets the "get" pointer. The get pointer is an index into the command buffer + // considered as an array of CommandBufferEntry. + bool set_get(CommandBufferOffset get) { + if (get < entry_count_) { + get_ = get; + return true; + } + return false; + } + // Sets the "put" pointer. The put pointer is an index into the command // buffer considered as an array of CommandBufferEntry. void set_put(CommandBufferOffset put) { put_ = put; } @@ -54,7 +64,7 @@ class CommandParser { CommandBufferOffset get_; CommandBufferOffset put_; CommandBufferEntry *buffer_; - size_t entry_count_; + int32 entry_count_; AsyncAPIInterface *handler_; }; diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc index 4d3623d..2cc87c5 100644 --- a/gpu/command_buffer/service/common_decoder.cc +++ b/gpu/command_buffer/service/common_decoder.cc @@ -45,6 +45,17 @@ void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, return static_cast<int8*>(buffer.ptr) + offset; } +bool CommonDecoder::PushAddress(uint32 offset) { + if (call_stack_.size() < kMaxStackDepth) { + CommandAddress return_address(engine_->GetGetOffset()); + if (engine_->SetGetOffset(offset)) { + call_stack_.push(return_address); + return true; + } + } + return false; +} + const char* CommonDecoder::GetCommonCommandName( cmd::CommandId command_id) const { return cmd::GetCommandName(command_id); @@ -138,35 +149,50 @@ parse_error::ParseError CommonDecoder::HandleSetToken( parse_error::ParseError CommonDecoder::HandleJump( uint32 immediate_data_size, const cmd::Jump& args) { - DCHECK(false); // TODO(gman): Implement. + if (!engine_->SetGetOffset(args.offset)) { + return parse_error::kParseInvalidArguments; + } return parse_error::kParseNoError; } parse_error::ParseError CommonDecoder::HandleJumpRelative( uint32 immediate_data_size, const cmd::JumpRelative& args) { - DCHECK(false); // TODO(gman): Implement. + if (!engine_->SetGetOffset(engine_->GetGetOffset() + args.offset)) { + return parse_error::kParseInvalidArguments; + } return parse_error::kParseNoError; } parse_error::ParseError CommonDecoder::HandleCall( uint32 immediate_data_size, const cmd::Call& args) { - DCHECK(false); // TODO(gman): Implement. + if (!PushAddress(args.offset)) { + return parse_error::kParseInvalidArguments; + } return parse_error::kParseNoError; } parse_error::ParseError CommonDecoder::HandleCallRelative( uint32 immediate_data_size, const cmd::CallRelative& args) { - DCHECK(false); // TODO(gman): Implement. + if (!PushAddress(engine_->GetGetOffset() + args.offset)) { + return parse_error::kParseInvalidArguments; + } return parse_error::kParseNoError; } parse_error::ParseError CommonDecoder::HandleReturn( uint32 immediate_data_size, const cmd::Return& args) { - DCHECK(false); // TODO(gman): Implement. + if (call_stack_.empty()) { + return parse_error::kParseInvalidArguments; + } + CommandAddress return_address = call_stack_.top(); + call_stack_.pop(); + if (!engine_->SetGetOffset(return_address.offset)) { + return parse_error::kParseInvalidArguments; + } return parse_error::kParseNoError; } diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h index 11ca5fc..051a626 100644 --- a/gpu/command_buffer/service/common_decoder.h +++ b/gpu/command_buffer/service/common_decoder.h @@ -6,6 +6,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_COMMON_DECODER_H_ #include <map> +#include <stack> #include "base/linked_ptr.h" #include "base/scoped_ptr.h" #include "gpu/command_buffer/service/cmd_parser.h" @@ -20,6 +21,8 @@ class CommonDecoder : public AsyncAPIInterface { public: typedef parse_error::ParseError ParseError; + static const unsigned int kMaxStackDepth = 32; + // A bucket is a buffer to help collect memory across a command buffer. When // creating a command buffer implementation of an existing API, sometimes that // API has functions that take a pointer to data. A good example is OpenGL's @@ -143,10 +146,23 @@ class CommonDecoder : public AsyncAPIInterface { #undef COMMON_COMMAND_BUFFER_CMD_OP + // Pushes an address on the call stack. + bool PushAddress(uint32 offset); + CommandBufferEngine* engine_; typedef std::map<uint32, linked_ptr<Bucket> > BucketMap; BucketMap buckets_; + + // The value put on the call stack. + struct CommandAddress { + explicit CommandAddress(uint32 _offset) + : offset(_offset) { + } + + uint32 offset; + }; + std::stack<CommandAddress> call_stack_; }; } // namespace gpu diff --git a/gpu/command_buffer/service/common_decoder_unittest.cc b/gpu/command_buffer/service/common_decoder_unittest.cc index 9a2db70..b2c369d 100644 --- a/gpu/command_buffer/service/common_decoder_unittest.cc +++ b/gpu/command_buffer/service/common_decoder_unittest.cc @@ -70,17 +70,23 @@ class TestCommonDecoder : public CommonDecoder { class MockCommandBufferEngine : public CommandBufferEngine { public: - static const int32 kValidShmId = 1; + static const int32 kStartValidShmId = 1; + static const int32 kValidShmId = 2; + static const int32 kInvalidShmId = 3; + static const size_t kBufferSize = 1024; + static const uint32 kValidOffset = kBufferSize / 2; + static const uint32 kInvalidOffset = kBufferSize; MockCommandBufferEngine() : CommandBufferEngine(), - token_() { + token_(), + get_offset_(0) { } // Overridden from CommandBufferEngine. virtual Buffer GetSharedMemoryBuffer(int32 shm_id) { Buffer buffer; - if (shm_id == kValidShmId) { + if (IsValidSharedMemoryId(shm_id)) { buffer.ptr = buffer_; buffer.size = kBufferSize; } @@ -95,7 +101,7 @@ class MockCommandBufferEngine : public CommandBufferEngine { uint32 GetSharedMemoryOffset(const void* memory) { ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0]; - DCHECK(offset >= 0); + DCHECK_GE(offset, 0); DCHECK(offset < kBufferSize); return static_cast<uint32>(offset); } @@ -109,11 +115,28 @@ class MockCommandBufferEngine : public CommandBufferEngine { return token_; } + // Overridden from CommandBufferEngine. + virtual bool SetGetOffset(int32 offset) { + if (offset < kBufferSize) { + get_offset_ = offset; + return true; + } + return false; + } + + // Overridden from CommandBufferEngine. + virtual int32 GetGetOffset() { + return get_offset_; + } + private: - static const size_t kBufferSize = 1024; + bool IsValidSharedMemoryId(int32 shm_id) { + return shm_id == kValidShmId || shm_id == kStartValidShmId; + } int8 buffer_[kBufferSize]; int32 token_; + int32 get_offset_; }; class CommonDecoderTest : public testing::Test { @@ -145,6 +168,10 @@ class CommonDecoderTest : public testing::Test { TestCommonDecoder decoder_; }; +TEST_F(CommonDecoderTest, Initialize) { + EXPECT_EQ(0u, engine_.GetGetOffset()); +} + TEST_F(CommonDecoderTest, HandleNoop) { cmd::Noop cmd; const uint32 kSkipCount = 5; @@ -164,28 +191,117 @@ TEST_F(CommonDecoderTest, SetToken) { } TEST_F(CommonDecoderTest, Jump) { - // cmd::Jump cmd; - // TODO(gman): implement. + cmd::Jump cmd; + // Check valid args succeed. + cmd.Init(MockCommandBufferEngine::kValidOffset); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + EXPECT_EQ(MockCommandBufferEngine::kValidOffset, + engine_.GetGetOffset()); + // Check invalid offset fails. + cmd.Init(MockCommandBufferEngine::kInvalidOffset); + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); + EXPECT_EQ(MockCommandBufferEngine::kValidOffset, + engine_.GetGetOffset()); } +// NOTE: The read_pointer checks for relative commands do not take into account +// that the actual implementation of CommandBufferEngine uses the parse +// which will advance the read pointer to the start of the next command. + TEST_F(CommonDecoderTest, JumpRelative) { - // cmd::JumpRelative cmd; - // TODO(gman): implement. + cmd::JumpRelative cmd; + // Check valid positive offset succeeds. + const int32 kPositiveOffset = 16; + cmd.Init(kPositiveOffset); + uint32 read_pointer = engine_.GetGetOffset(); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer + kPositiveOffset, engine_.GetGetOffset()); + // Check valid negative offset succeeds. + const int32 kNegativeOffset = -8; + read_pointer = engine_.GetGetOffset(); + cmd.Init(kNegativeOffset); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer + kNegativeOffset, engine_.GetGetOffset()); + // Check invalid offset fails. + cmd.Init(MockCommandBufferEngine::kInvalidOffset); + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer + kNegativeOffset, engine_.GetGetOffset()); } TEST_F(CommonDecoderTest, Call) { - // cmd::Call cmd; - // TODO(gman): implement. + cmd::Call cmd; + // Check valid args succeed. + cmd.Init(MockCommandBufferEngine::kValidOffset); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + EXPECT_EQ(MockCommandBufferEngine::kValidOffset, + engine_.GetGetOffset()); + // Check invalid offset fails. + cmd.Init(MockCommandBufferEngine::kInvalidOffset); + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); + EXPECT_EQ(MockCommandBufferEngine::kValidOffset, + engine_.GetGetOffset()); + // Check that the call values are on the stack. + cmd::Return return_cmd; + return_cmd.Init(); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); + EXPECT_EQ(0u, engine_.GetGetOffset()); + // Check that stack overflow fails. + cmd.Init(MockCommandBufferEngine::kValidOffset); + for (unsigned int ii = 0; ii < CommonDecoder::kMaxStackDepth; ++ii) { + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + } + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); } TEST_F(CommonDecoderTest, CallRelative) { - // cmd::CallRelative cmd; - // TODO(gman): implement. + cmd::CallRelative cmd; + // Check valid positive offset succeeds. + const int32 kPositiveOffset = 16; + cmd.Init(kPositiveOffset); + uint32 read_pointer_1 = engine_.GetGetOffset(); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer_1 + kPositiveOffset, engine_.GetGetOffset()); + // Check valid negative offset succeeds. + const int32 kNegativeOffset = -8; + uint32 read_pointer_2 = engine_.GetGetOffset(); + cmd.Init(kNegativeOffset); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer_2 + kNegativeOffset, engine_.GetGetOffset()); + // Check invalid offset fails. + cmd.Init(MockCommandBufferEngine::kInvalidOffset); + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); + // See note above. + EXPECT_EQ(read_pointer_2 + kNegativeOffset, engine_.GetGetOffset()); + + // Check that the call values are on the stack. + cmd::Return return_cmd; + return_cmd.Init(); + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); + // See note above. + EXPECT_EQ(read_pointer_1 + kPositiveOffset, engine_.GetGetOffset()); + + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); + // See note above. + EXPECT_EQ(0u, engine_.GetGetOffset()); + // Check that stack overflow fails. + cmd.Init(kPositiveOffset); + for (unsigned int ii = 0; ii < CommonDecoder::kMaxStackDepth; ++ii) { + EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); + } + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); } TEST_F(CommonDecoderTest, Return) { - // cmd::Return cmd; - // TODO(gman): implement. + // Success is tested by Call and CallRelative + // Test that an empty stack fails. + cmd::Return cmd; + cmd.Init(); + EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); } TEST_F(CommonDecoderTest, SetBucketSize) { @@ -413,6 +529,5 @@ TEST_F(CommonDecoderTest, GetBucketData) { EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); } - } // namespace gpu diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index 1f8771a..c7fd244 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -226,6 +226,18 @@ class GLES2DecoderTest : public testing::Test { DCHECK(false); } + // Overridden from CommandBufferEngine. + virtual bool SetGetOffset(int32 offset) { + DCHECK(false); + return false; + } + + // Overridden from CommandBufferEngine. + virtual int32 GetGetOffset() { + DCHECK(false); + return 0; + } + private: scoped_array<int8> data_; Buffer valid_buffer_; diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc index f88e3a1..8697c8b 100644 --- a/gpu/command_buffer/service/gpu_processor.cc +++ b/gpu/command_buffer/service/gpu_processor.cc @@ -80,4 +80,16 @@ void GPUProcessor::set_token(int32 token) { command_buffer_->SetToken(token); } +bool GPUProcessor::SetGetOffset(int32 offset) { + if (parser_->set_get(offset)) { + command_buffer_->SetGetOffset(static_cast<int32>(parser_->get())); + return true; + } + return false; +} + +int32 GPUProcessor::GetGetOffset() { + return parser_->get(); +} + } // namespace gpu diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h index 6bcf317..dd22ac4 100644 --- a/gpu/command_buffer/service/gpu_processor.h +++ b/gpu/command_buffer/service/gpu_processor.h @@ -41,6 +41,8 @@ class GPUProcessor : public base::RefCounted<GPUProcessor>, // Implementation of CommandBufferEngine. virtual Buffer GetSharedMemoryBuffer(int32 shm_id); virtual void set_token(int32 token); + virtual bool SetGetOffset(int32 offset); + virtual int32 GetGetOffset(); private: // The GPUProcessor holds a weak reference to the CommandBuffer. The |