summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-28 21:50:24 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-28 21:50:24 +0000
commit67e5077346cde830210611c2f00fb550d563fcd3 (patch)
tree2b44cd8f1774858d627ae7d43c36cc4a176afcd4 /gpu
parenta359ecc79d700a0d40701a29d9f1ca226136cc21 (diff)
downloadchromium_src-67e5077346cde830210611c2f00fb550d563fcd3.zip
chromium_src-67e5077346cde830210611c2f00fb550d563fcd3.tar.gz
chromium_src-67e5077346cde830210611c2f00fb550d563fcd3.tar.bz2
Add commands Jump, Call and Return
This is the minimal change version. There were 3 possible solution: #1) Remove these commands #2) Change the command buffers so the client side can not see the "get" pointer and therefore force the client side to use tokens to say in sync. It's the cleaner solution. It lets you put commands in any shared memory thereby getting rid of the ring buffer commands. But, it required major changes. After going down that path for an entire day I punted for... #3) Implement the commands assuming there is only one buffer the commands can be in (what is currently called the ring_buffer). With the jump commands available it no longer has to be used as a ring buffer. A Pepper or NaCl app can use it however they want but, unlike solution #2 they only get the one buffer. TEST=none BUG=none Review URL: http://codereview.chromium.org/555129 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@37446 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-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