summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper.cc22
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper.h43
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper_test.cc15
-rw-r--r--gpu/command_buffer/common/cmd_buffer_common.h52
-rw-r--r--gpu/command_buffer/service/cmd_buffer_engine.h6
-rw-r--r--gpu/command_buffer/service/cmd_parser.cc2
-rw-r--r--gpu/command_buffer/service/cmd_parser.h12
-rw-r--r--gpu/command_buffer/service/common_decoder.cc36
-rw-r--r--gpu/command_buffer/service/common_decoder.h16
-rw-r--r--gpu/command_buffer/service/common_decoder_unittest.cc147
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc12
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc12
-rw-r--r--gpu/command_buffer/service/gpu_processor.h2
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