Index: gpu/command_buffer/service/common_decoder.cc |
=================================================================== |
--- gpu/command_buffer/service/common_decoder.cc (revision 34064) |
+++ gpu/command_buffer/service/common_decoder.cc (working copy) |
@@ -35,6 +35,30 @@ |
namespace command_buffer { |
+const void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const { |
+ if (OffsetSizeValid(offset, size)) { |
+ return data_.get() + offset; |
+ } |
+ return NULL; |
+} |
+ |
+void CommonDecoder::Bucket::SetSize(size_t size) { |
+ if (size != size_) { |
+ data_.reset(size ? new int8[size] : NULL); |
+ size_ = size; |
+ memset(data_.get(), 0, size); |
+ } |
+} |
+ |
+bool CommonDecoder::Bucket::SetData( |
+ const void* src, size_t offset, size_t size) { |
+ if (OffsetSizeValid(offset, size)) { |
+ memcpy(data_.get() + offset, src, size); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, |
unsigned int offset, |
unsigned int size) { |
@@ -53,8 +77,25 @@ |
return cmd::GetCommandName(command_id); |
} |
+CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const { |
+ BucketMap::const_iterator iter(buckets_.find(bucket_id)); |
+ return iter != buckets_.end() ? &(*iter->second) : NULL; |
+} |
+ |
namespace { |
+// Returns the address of the first byte after a struct. |
+template <typename T> |
+const void* AddressAfterStruct(const T& pod) { |
+ return reinterpret_cast<const uint8*>(&pod) + sizeof(pod); |
+} |
+ |
+// Returns the address of the frst byte after the struct. |
+template <typename RETURN_TYPE, typename COMMAND_TYPE> |
+RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) { |
+ return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); |
+} |
+ |
// A struct to hold info about each command. |
struct CommandInfo { |
int arg_flags; // How to handle the arguments for this command |
@@ -87,11 +128,13 @@ |
unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); |
if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || |
(info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { |
+ uint32 immediate_data_size = |
+ (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT |
switch (command) { |
#define COMMON_COMMAND_BUFFER_CMD_OP(name) \ |
case cmd::name::kCmdId: \ |
return Handle ## name( \ |
- arg_count, \ |
+ immediate_data_size, \ |
*static_cast<const cmd::name*>(cmd_data)); \ |
COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) |
@@ -107,85 +150,148 @@ |
} |
parse_error::ParseError CommonDecoder::HandleNoop( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::Noop& args) { |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleSetToken( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::SetToken& args) { |
engine_->set_token(args.token); |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleJump( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::Jump& args) { |
DCHECK(false); // TODO(gman): Implement. |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleJumpRelative( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::JumpRelative& args) { |
DCHECK(false); // TODO(gman): Implement. |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleCall( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::Call& args) { |
DCHECK(false); // TODO(gman): Implement. |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleCallRelative( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::CallRelative& args) { |
DCHECK(false); // TODO(gman): Implement. |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleReturn( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::Return& args) { |
DCHECK(false); // TODO(gman): Implement. |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleSetBucketSize( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::SetBucketSize& args) { |
- DCHECK(false); // TODO(gman): Implement. |
+ uint32 bucket_id = args.bucket_id; |
+ uint32 size = args.size; |
+ |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) { |
+ bucket = new Bucket(); |
+ buckets_[bucket_id] = linked_ptr<Bucket>(bucket); |
+ } |
+ |
+ bucket->SetSize(size); |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleSetBucketData( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::SetBucketData& args) { |
- DCHECK(false); // TODO(gman): Implement. |
+ uint32 bucket_id = args.bucket_id; |
+ uint32 offset = args.offset; |
+ uint32 size = args.size; |
+ const void* data = GetSharedMemoryAs<const void*>( |
+ args.shared_memory_id, args.shared_memory_offset, size); |
+ if (!data) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ if (!bucket->SetData(data, offset, size)) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ |
return parse_error::kParseNoError; |
} |
parse_error::ParseError CommonDecoder::HandleSetBucketDataImmediate( |
- uint32 arg_count, |
+ uint32 immediate_data_size, |
const cmd::SetBucketDataImmediate& args) { |
- DCHECK(false); // TODO(gman): Implement. |
+ const void* data = GetImmediateDataAs<const void*>(args); |
+ uint32 bucket_id = args.bucket_id; |
+ uint32 offset = args.offset; |
+ uint32 size = args.size; |
+ if (size > immediate_data_size) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ if (!bucket->SetData(data, offset, size)) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
return parse_error::kParseNoError; |
} |
-parse_error::ParseError CommonDecoder::HandleGetResultSize( |
- uint32 arg_count, |
- const cmd::GetResultSize& args) { |
- DCHECK(false); // TODO(gman): Implement. |
+parse_error::ParseError CommonDecoder::HandleGetBucketSize( |
+ uint32 immediate_data_size, |
+ const cmd::GetBucketSize& args) { |
+ uint32 bucket_id = args.bucket_id; |
+ uint32* data = GetSharedMemoryAs<uint32*>( |
+ args.shared_memory_id, args.shared_memory_offset, sizeof(*data)); |
+ if (!data) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ *data = bucket->size(); |
return parse_error::kParseNoError; |
} |
-parse_error::ParseError CommonDecoder::HandleGetResultData( |
- uint32 arg_count, |
- const cmd::GetResultData& args) { |
- DCHECK(false); // TODO(gman): Implement. |
+parse_error::ParseError CommonDecoder::HandleGetBucketData( |
+ uint32 immediate_data_size, |
+ const cmd::GetBucketData& args) { |
+ uint32 bucket_id = args.bucket_id; |
+ uint32 offset = args.offset; |
+ uint32 size = args.size; |
+ void* data = GetSharedMemoryAs<void*>( |
+ args.shared_memory_id, args.shared_memory_offset, size); |
+ if (!data) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ Bucket* bucket = GetBucket(bucket_id); |
+ if (!bucket) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ const void* src = bucket->GetData(offset, size); |
+ if (!src) { |
+ return parse_error::kParseInvalidArguments; |
+ } |
+ memcpy(data, src, size); |
return parse_error::kParseNoError; |
} |