JSONStringValueSerializer takes a StringPiece instead of std::string&.
[chromium-blink-merge.git] / gpu / command_buffer / service / common_decoder.cc
blobf40c7218ad12d8de2ed0af128c231774cb7a77b0
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/common_decoder.h"
6 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
8 namespace gpu {
10 const CommonDecoder::CommandInfo CommonDecoder::command_info[] = {
11 #define COMMON_COMMAND_BUFFER_CMD_OP(name) \
12 { \
13 &CommonDecoder::Handle##name, cmd::name::kArgFlags, \
14 cmd::name::cmd_flags, \
15 sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, \
16 } \
17 , /* NOLINT */
18 COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
19 #undef COMMON_COMMAND_BUFFER_CMD_OP
23 CommonDecoder::Bucket::Bucket() : size_(0) {}
25 CommonDecoder::Bucket::~Bucket() {}
27 void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const {
28 if (OffsetSizeValid(offset, size)) {
29 return data_.get() + offset;
31 return NULL;
34 void CommonDecoder::Bucket::SetSize(size_t size) {
35 if (size != size_) {
36 data_.reset(size ? new int8[size] : NULL);
37 size_ = size;
38 memset(data_.get(), 0, size);
42 bool CommonDecoder::Bucket::SetData(
43 const void* src, size_t offset, size_t size) {
44 if (OffsetSizeValid(offset, size)) {
45 memcpy(data_.get() + offset, src, size);
46 return true;
48 return false;
51 void CommonDecoder::Bucket::SetFromString(const char* str) {
52 // Strings are passed NULL terminated to distinguish between empty string
53 // and no string.
54 if (!str) {
55 SetSize(0);
56 } else {
57 size_t size = strlen(str) + 1;
58 SetSize(size);
59 SetData(str, 0, size);
63 bool CommonDecoder::Bucket::GetAsString(std::string* str) {
64 DCHECK(str);
65 if (size_ == 0) {
66 return false;
68 str->assign(GetDataAs<const char*>(0, size_ - 1), size_ - 1);
69 return true;
72 CommonDecoder::CommonDecoder() : engine_(NULL) {}
74 CommonDecoder::~CommonDecoder() {}
76 void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
77 unsigned int data_offset,
78 unsigned int data_size) {
79 CHECK(engine_);
80 scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id);
81 if (!buffer.get())
82 return NULL;
83 return buffer->GetDataAddress(data_offset, data_size);
86 scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer(
87 unsigned int shm_id) {
88 return engine_->GetSharedMemoryBuffer(shm_id);
91 const char* CommonDecoder::GetCommonCommandName(
92 cmd::CommandId command_id) const {
93 return cmd::GetCommandName(command_id);
96 CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const {
97 BucketMap::const_iterator iter(buckets_.find(bucket_id));
98 return iter != buckets_.end() ? &(*iter->second) : NULL;
101 CommonDecoder::Bucket* CommonDecoder::CreateBucket(uint32 bucket_id) {
102 Bucket* bucket = GetBucket(bucket_id);
103 if (!bucket) {
104 bucket = new Bucket();
105 buckets_[bucket_id] = linked_ptr<Bucket>(bucket);
107 return bucket;
110 namespace {
112 // Returns the address of the first byte after a struct.
113 template <typename T>
114 const void* AddressAfterStruct(const T& pod) {
115 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
118 // Returns the address of the frst byte after the struct.
119 template <typename RETURN_TYPE, typename COMMAND_TYPE>
120 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) {
121 return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod)));
124 } // anonymous namespace.
126 // Decode command with its arguments, and call the corresponding method.
127 // Note: args is a pointer to the command buffer. As such, it could be changed
128 // by a (malicious) client at any time, so if validation has to happen, it
129 // should operate on a copy of them.
130 error::Error CommonDecoder::DoCommonCommand(
131 unsigned int command,
132 unsigned int arg_count,
133 const void* cmd_data) {
134 if (command < arraysize(command_info)) {
135 const CommandInfo& info = command_info[command];
136 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
137 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
138 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
139 uint32 immediate_data_size =
140 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
141 return (this->*info.cmd_handler)(immediate_data_size, cmd_data);
142 } else {
143 return error::kInvalidArguments;
146 return error::kUnknownCommand;
149 error::Error CommonDecoder::HandleNoop(
150 uint32 immediate_data_size,
151 const void* cmd_data) {
152 return error::kNoError;
155 error::Error CommonDecoder::HandleSetToken(
156 uint32 immediate_data_size,
157 const void* cmd_data) {
158 const cmd::SetToken& args = *static_cast<const cmd::SetToken*>(cmd_data);
159 engine_->set_token(args.token);
160 return error::kNoError;
163 error::Error CommonDecoder::HandleSetBucketSize(
164 uint32 immediate_data_size,
165 const void* cmd_data) {
166 const cmd::SetBucketSize& args =
167 *static_cast<const cmd::SetBucketSize*>(cmd_data);
168 uint32 bucket_id = args.bucket_id;
169 uint32 size = args.size;
171 Bucket* bucket = CreateBucket(bucket_id);
172 bucket->SetSize(size);
173 return error::kNoError;
176 error::Error CommonDecoder::HandleSetBucketData(
177 uint32 immediate_data_size,
178 const void* cmd_data) {
179 const cmd::SetBucketData& args =
180 *static_cast<const cmd::SetBucketData*>(cmd_data);
181 uint32 bucket_id = args.bucket_id;
182 uint32 offset = args.offset;
183 uint32 size = args.size;
184 const void* data = GetSharedMemoryAs<const void*>(
185 args.shared_memory_id, args.shared_memory_offset, size);
186 if (!data) {
187 return error::kInvalidArguments;
189 Bucket* bucket = GetBucket(bucket_id);
190 if (!bucket) {
191 return error::kInvalidArguments;
193 if (!bucket->SetData(data, offset, size)) {
194 return error::kInvalidArguments;
197 return error::kNoError;
200 error::Error CommonDecoder::HandleSetBucketDataImmediate(
201 uint32 immediate_data_size,
202 const void* cmd_data) {
203 const cmd::SetBucketDataImmediate& args =
204 *static_cast<const cmd::SetBucketDataImmediate*>(cmd_data);
205 const void* data = GetImmediateDataAs<const void*>(args);
206 uint32 bucket_id = args.bucket_id;
207 uint32 offset = args.offset;
208 uint32 size = args.size;
209 if (size > immediate_data_size) {
210 return error::kInvalidArguments;
212 Bucket* bucket = GetBucket(bucket_id);
213 if (!bucket) {
214 return error::kInvalidArguments;
216 if (!bucket->SetData(data, offset, size)) {
217 return error::kInvalidArguments;
219 return error::kNoError;
222 error::Error CommonDecoder::HandleGetBucketStart(
223 uint32 immediate_data_size,
224 const void* cmd_data) {
225 const cmd::GetBucketStart& args =
226 *static_cast<const cmd::GetBucketStart*>(cmd_data);
227 uint32 bucket_id = args.bucket_id;
228 uint32* result = GetSharedMemoryAs<uint32*>(
229 args.result_memory_id, args.result_memory_offset, sizeof(*result));
230 int32 data_memory_id = args.data_memory_id;
231 uint32 data_memory_offset = args.data_memory_offset;
232 uint32 data_memory_size = args.data_memory_size;
233 uint8* data = NULL;
234 if (data_memory_size != 0 || data_memory_id != 0 || data_memory_offset != 0) {
235 data = GetSharedMemoryAs<uint8*>(
236 args.data_memory_id, args.data_memory_offset, args.data_memory_size);
237 if (!data) {
238 return error::kInvalidArguments;
241 if (!result) {
242 return error::kInvalidArguments;
244 // Check that the client initialized the result.
245 if (*result != 0) {
246 return error::kInvalidArguments;
248 Bucket* bucket = GetBucket(bucket_id);
249 if (!bucket) {
250 return error::kInvalidArguments;
252 uint32 bucket_size = bucket->size();
253 *result = bucket_size;
254 if (data) {
255 uint32 size = std::min(data_memory_size, bucket_size);
256 memcpy(data, bucket->GetData(0, size), size);
258 return error::kNoError;
261 error::Error CommonDecoder::HandleGetBucketData(
262 uint32 immediate_data_size,
263 const void* cmd_data) {
264 const cmd::GetBucketData& args =
265 *static_cast<const cmd::GetBucketData*>(cmd_data);
266 uint32 bucket_id = args.bucket_id;
267 uint32 offset = args.offset;
268 uint32 size = args.size;
269 void* data = GetSharedMemoryAs<void*>(
270 args.shared_memory_id, args.shared_memory_offset, size);
271 if (!data) {
272 return error::kInvalidArguments;
274 Bucket* bucket = GetBucket(bucket_id);
275 if (!bucket) {
276 return error::kInvalidArguments;
278 const void* src = bucket->GetData(offset, size);
279 if (!src) {
280 return error::kInvalidArguments;
282 memcpy(data, src, size);
283 return error::kNoError;
286 } // namespace gpu