Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / common_decoder.cc
blob86a37ba77e5fb8dd94c4c285ed0ce3351c46ac92
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 CommonDecoder::Bucket::Bucket() : size_(0) {}
12 CommonDecoder::Bucket::~Bucket() {}
14 void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const {
15 if (OffsetSizeValid(offset, size)) {
16 return data_.get() + offset;
18 return NULL;
21 void CommonDecoder::Bucket::SetSize(size_t size) {
22 if (size != size_) {
23 data_.reset(size ? new int8[size] : NULL);
24 size_ = size;
25 memset(data_.get(), 0, size);
29 bool CommonDecoder::Bucket::SetData(
30 const void* src, size_t offset, size_t size) {
31 if (OffsetSizeValid(offset, size)) {
32 memcpy(data_.get() + offset, src, size);
33 return true;
35 return false;
38 void CommonDecoder::Bucket::SetFromString(const char* str) {
39 // Strings are passed NULL terminated to distinguish between empty string
40 // and no string.
41 if (!str) {
42 SetSize(0);
43 } else {
44 size_t size = strlen(str) + 1;
45 SetSize(size);
46 SetData(str, 0, size);
50 bool CommonDecoder::Bucket::GetAsString(std::string* str) {
51 DCHECK(str);
52 if (size_ == 0) {
53 return false;
55 str->assign(GetDataAs<const char*>(0, size_ - 1), size_ - 1);
56 return true;
59 CommonDecoder::CommonDecoder() : engine_(NULL) {}
61 CommonDecoder::~CommonDecoder() {}
63 void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
64 unsigned int data_offset,
65 unsigned int data_size) {
66 CHECK(engine_);
67 scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id);
68 if (!buffer.get())
69 return NULL;
70 return buffer->GetDataAddress(data_offset, data_size);
73 scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer(
74 unsigned int shm_id) {
75 return engine_->GetSharedMemoryBuffer(shm_id);
78 const char* CommonDecoder::GetCommonCommandName(
79 cmd::CommandId command_id) const {
80 return cmd::GetCommandName(command_id);
83 CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const {
84 BucketMap::const_iterator iter(buckets_.find(bucket_id));
85 return iter != buckets_.end() ? &(*iter->second) : NULL;
88 CommonDecoder::Bucket* CommonDecoder::CreateBucket(uint32 bucket_id) {
89 Bucket* bucket = GetBucket(bucket_id);
90 if (!bucket) {
91 bucket = new Bucket();
92 buckets_[bucket_id] = linked_ptr<Bucket>(bucket);
94 return bucket;
97 namespace {
99 // Returns the address of the first byte after a struct.
100 template <typename T>
101 const void* AddressAfterStruct(const T& pod) {
102 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod);
105 // Returns the address of the frst byte after the struct.
106 template <typename RETURN_TYPE, typename COMMAND_TYPE>
107 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) {
108 return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod)));
111 // TODO(vmiura): Looks like this g_command_info is duplicated in
112 // common_decoder.cc
113 // and gles2_cmd_decoder.cc. Fix it!
115 // A struct to hold info about each command.
116 struct CommandInfo {
117 uint8 arg_flags; // How to handle the arguments for this command
118 uint8 cmd_flags; // How to handle this command
119 uint16 arg_count; // How many arguments are expected for this command.
122 // A table of CommandInfo for all the commands.
123 const CommandInfo g_command_info[] = {
124 #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \
125 cmd::name::kArgFlags, \
126 cmd::name::cmd_flags, \
127 sizeof(cmd::name) / sizeof(CommandBufferEntry) - 1, }, /* NOLINT */
129 COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
131 #undef COMMON_COMMAND_BUFFER_CMD_OP
134 } // anonymous namespace.
136 // Decode command with its arguments, and call the corresponding method.
137 // Note: args is a pointer to the command buffer. As such, it could be changed
138 // by a (malicious) client at any time, so if validation has to happen, it
139 // should operate on a copy of them.
140 error::Error CommonDecoder::DoCommonCommand(
141 unsigned int command,
142 unsigned int arg_count,
143 const void* cmd_data) {
144 if (command < arraysize(g_command_info)) {
145 const CommandInfo& info = g_command_info[command];
146 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count);
147 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) ||
148 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) {
149 uint32 immediate_data_size =
150 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT
151 switch (command) {
152 #define COMMON_COMMAND_BUFFER_CMD_OP(name) \
153 case cmd::name::kCmdId: \
154 return Handle ## name( \
155 immediate_data_size, \
156 *static_cast<const cmd::name*>(cmd_data)); \
158 COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP)
160 #undef COMMON_COMMAND_BUFFER_CMD_OP
162 } else {
163 return error::kInvalidArguments;
166 return error::kUnknownCommand;
169 error::Error CommonDecoder::HandleNoop(
170 uint32 immediate_data_size,
171 const cmd::Noop& args) {
172 return error::kNoError;
175 error::Error CommonDecoder::HandleSetToken(
176 uint32 immediate_data_size,
177 const cmd::SetToken& args) {
178 engine_->set_token(args.token);
179 return error::kNoError;
182 error::Error CommonDecoder::HandleSetBucketSize(
183 uint32 immediate_data_size,
184 const cmd::SetBucketSize& args) {
185 uint32 bucket_id = args.bucket_id;
186 uint32 size = args.size;
188 Bucket* bucket = CreateBucket(bucket_id);
189 bucket->SetSize(size);
190 return error::kNoError;
193 error::Error CommonDecoder::HandleSetBucketData(
194 uint32 immediate_data_size,
195 const cmd::SetBucketData& args) {
196 uint32 bucket_id = args.bucket_id;
197 uint32 offset = args.offset;
198 uint32 size = args.size;
199 const void* data = GetSharedMemoryAs<const void*>(
200 args.shared_memory_id, args.shared_memory_offset, size);
201 if (!data) {
202 return error::kInvalidArguments;
204 Bucket* bucket = GetBucket(bucket_id);
205 if (!bucket) {
206 return error::kInvalidArguments;
208 if (!bucket->SetData(data, offset, size)) {
209 return error::kInvalidArguments;
212 return error::kNoError;
215 error::Error CommonDecoder::HandleSetBucketDataImmediate(
216 uint32 immediate_data_size,
217 const cmd::SetBucketDataImmediate& args) {
218 const void* data = GetImmediateDataAs<const void*>(args);
219 uint32 bucket_id = args.bucket_id;
220 uint32 offset = args.offset;
221 uint32 size = args.size;
222 if (size > immediate_data_size) {
223 return error::kInvalidArguments;
225 Bucket* bucket = GetBucket(bucket_id);
226 if (!bucket) {
227 return error::kInvalidArguments;
229 if (!bucket->SetData(data, offset, size)) {
230 return error::kInvalidArguments;
232 return error::kNoError;
235 error::Error CommonDecoder::HandleGetBucketStart(
236 uint32 immediate_data_size,
237 const cmd::GetBucketStart& args) {
238 uint32 bucket_id = args.bucket_id;
239 uint32* result = GetSharedMemoryAs<uint32*>(
240 args.result_memory_id, args.result_memory_offset, sizeof(*result));
241 int32 data_memory_id = args.data_memory_id;
242 uint32 data_memory_offset = args.data_memory_offset;
243 uint32 data_memory_size = args.data_memory_size;
244 uint8* data = NULL;
245 if (data_memory_size != 0 || data_memory_id != 0 || data_memory_offset != 0) {
246 data = GetSharedMemoryAs<uint8*>(
247 args.data_memory_id, args.data_memory_offset, args.data_memory_size);
248 if (!data) {
249 return error::kInvalidArguments;
252 if (!result) {
253 return error::kInvalidArguments;
255 // Check that the client initialized the result.
256 if (*result != 0) {
257 return error::kInvalidArguments;
259 Bucket* bucket = GetBucket(bucket_id);
260 if (!bucket) {
261 return error::kInvalidArguments;
263 uint32 bucket_size = bucket->size();
264 *result = bucket_size;
265 if (data) {
266 uint32 size = std::min(data_memory_size, bucket_size);
267 memcpy(data, bucket->GetData(0, size), size);
269 return error::kNoError;
272 error::Error CommonDecoder::HandleGetBucketData(
273 uint32 immediate_data_size,
274 const cmd::GetBucketData& args) {
275 uint32 bucket_id = args.bucket_id;
276 uint32 offset = args.offset;
277 uint32 size = args.size;
278 void* data = GetSharedMemoryAs<void*>(
279 args.shared_memory_id, args.shared_memory_offset, size);
280 if (!data) {
281 return error::kInvalidArguments;
283 Bucket* bucket = GetBucket(bucket_id);
284 if (!bucket) {
285 return error::kInvalidArguments;
287 const void* src = bucket->GetData(offset, size);
288 if (!src) {
289 return error::kInvalidArguments;
291 memcpy(data, src, size);
292 return error::kNoError;
295 } // namespace gpu