| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009, Google Inc. | 2 * Copyright 2009, Google Inc. |
| 3 * All rights reserved. | 3 * All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "gpu/command_buffer/service/precompile.h" | 32 #include "gpu/command_buffer/service/precompile.h" |
| 33 #include "gpu/command_buffer/service/common_decoder.h" | 33 #include "gpu/command_buffer/service/common_decoder.h" |
| 34 #include "gpu/command_buffer/service/cmd_buffer_engine.h" | 34 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
| 35 | 35 |
| 36 namespace command_buffer { | 36 namespace command_buffer { |
| 37 | 37 |
| 38 const void* CommonDecoder::Bucket::GetData(size_t offset, size_t size) const { |
| 39 if (OffsetSizeValid(offset, size)) { |
| 40 return data_.get() + offset; |
| 41 } |
| 42 return NULL; |
| 43 } |
| 44 |
| 45 void CommonDecoder::Bucket::SetSize(size_t size) { |
| 46 if (size != size_) { |
| 47 data_.reset(size ? new int8[size] : NULL); |
| 48 size_ = size; |
| 49 memset(data_.get(), 0, size); |
| 50 } |
| 51 } |
| 52 |
| 53 bool CommonDecoder::Bucket::SetData( |
| 54 const void* src, size_t offset, size_t size) { |
| 55 if (OffsetSizeValid(offset, size)) { |
| 56 memcpy(data_.get() + offset, src, size); |
| 57 return true; |
| 58 } |
| 59 return false; |
| 60 } |
| 61 |
| 38 void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, | 62 void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, |
| 39 unsigned int offset, | 63 unsigned int offset, |
| 40 unsigned int size) { | 64 unsigned int size) { |
| 41 void* shm_addr = engine_->GetSharedMemoryAddress(shm_id); | 65 void* shm_addr = engine_->GetSharedMemoryAddress(shm_id); |
| 42 if (!shm_addr) return NULL; | 66 if (!shm_addr) return NULL; |
| 43 size_t shm_size = engine_->GetSharedMemorySize(shm_id); | 67 size_t shm_size = engine_->GetSharedMemorySize(shm_id); |
| 44 unsigned int end = offset + size; | 68 unsigned int end = offset + size; |
| 45 if (end > shm_size || end < offset) { | 69 if (end > shm_size || end < offset) { |
| 46 return NULL; | 70 return NULL; |
| 47 } | 71 } |
| 48 return static_cast<int8 *>(shm_addr) + offset; | 72 return static_cast<int8 *>(shm_addr) + offset; |
| 49 } | 73 } |
| 50 | 74 |
| 51 const char* CommonDecoder::GetCommonCommandName( | 75 const char* CommonDecoder::GetCommonCommandName( |
| 52 cmd::CommandId command_id) const { | 76 cmd::CommandId command_id) const { |
| 53 return cmd::GetCommandName(command_id); | 77 return cmd::GetCommandName(command_id); |
| 54 } | 78 } |
| 55 | 79 |
| 80 CommonDecoder::Bucket* CommonDecoder::GetBucket(uint32 bucket_id) const { |
| 81 BucketMap::const_iterator iter(buckets_.find(bucket_id)); |
| 82 return iter != buckets_.end() ? &(*iter->second) : NULL; |
| 83 } |
| 84 |
| 56 namespace { | 85 namespace { |
| 57 | 86 |
| 87 // Returns the address of the first byte after a struct. |
| 88 template <typename T> |
| 89 const void* AddressAfterStruct(const T& pod) { |
| 90 return reinterpret_cast<const uint8*>(&pod) + sizeof(pod); |
| 91 } |
| 92 |
| 93 // Returns the address of the frst byte after the struct. |
| 94 template <typename RETURN_TYPE, typename COMMAND_TYPE> |
| 95 RETURN_TYPE GetImmediateDataAs(const COMMAND_TYPE& pod) { |
| 96 return static_cast<RETURN_TYPE>(const_cast<void*>(AddressAfterStruct(pod))); |
| 97 } |
| 98 |
| 58 // A struct to hold info about each command. | 99 // A struct to hold info about each command. |
| 59 struct CommandInfo { | 100 struct CommandInfo { |
| 60 int arg_flags; // How to handle the arguments for this command | 101 int arg_flags; // How to handle the arguments for this command |
| 61 int arg_count; // How many arguments are expected for this command. | 102 int arg_count; // How many arguments are expected for this command. |
| 62 }; | 103 }; |
| 63 | 104 |
| 64 // A table of CommandInfo for all the commands. | 105 // A table of CommandInfo for all the commands. |
| 65 const CommandInfo g_command_info[] = { | 106 const CommandInfo g_command_info[] = { |
| 66 #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \ | 107 #define COMMON_COMMAND_BUFFER_CMD_OP(name) { \ |
| 67 cmd::name::kArgFlags, \ | 108 cmd::name::kArgFlags, \ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 80 // should operate on a copy of them. | 121 // should operate on a copy of them. |
| 81 parse_error::ParseError CommonDecoder::DoCommonCommand( | 122 parse_error::ParseError CommonDecoder::DoCommonCommand( |
| 82 unsigned int command, | 123 unsigned int command, |
| 83 unsigned int arg_count, | 124 unsigned int arg_count, |
| 84 const void* cmd_data) { | 125 const void* cmd_data) { |
| 85 if (command < arraysize(g_command_info)) { | 126 if (command < arraysize(g_command_info)) { |
| 86 const CommandInfo& info = g_command_info[command]; | 127 const CommandInfo& info = g_command_info[command]; |
| 87 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); | 128 unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); |
| 88 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || | 129 if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || |
| 89 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { | 130 (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { |
| 131 uint32 immediate_data_size = |
| 132 (arg_count - info_arg_count) * sizeof(CommandBufferEntry); // NOLINT |
| 90 switch (command) { | 133 switch (command) { |
| 91 #define COMMON_COMMAND_BUFFER_CMD_OP(name) \ | 134 #define COMMON_COMMAND_BUFFER_CMD_OP(name) \ |
| 92 case cmd::name::kCmdId: \ | 135 case cmd::name::kCmdId: \ |
| 93 return Handle ## name( \ | 136 return Handle ## name( \ |
| 94 arg_count, \ | 137 immediate_data_size, \ |
| 95 *static_cast<const cmd::name*>(cmd_data)); \ | 138 *static_cast<const cmd::name*>(cmd_data)); \ |
| 96 | 139 |
| 97 COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) | 140 COMMON_COMMAND_BUFFER_CMDS(COMMON_COMMAND_BUFFER_CMD_OP) |
| 98 | 141 |
| 99 #undef COMMON_COMMAND_BUFFER_CMD_OP | 142 #undef COMMON_COMMAND_BUFFER_CMD_OP |
| 100 } | 143 } |
| 101 } else { | 144 } else { |
| 102 return parse_error::kParseInvalidArguments; | 145 return parse_error::kParseInvalidArguments; |
| 103 } | 146 } |
| 104 } | 147 } |
| 105 return DoCommonCommand(command, arg_count, cmd_data); | 148 return DoCommonCommand(command, arg_count, cmd_data); |
| 106 return parse_error::kParseUnknownCommand; | 149 return parse_error::kParseUnknownCommand; |
| 107 } | 150 } |
| 108 | 151 |
| 109 parse_error::ParseError CommonDecoder::HandleNoop( | 152 parse_error::ParseError CommonDecoder::HandleNoop( |
| 110 uint32 arg_count, | 153 uint32 immediate_data_size, |
| 111 const cmd::Noop& args) { | 154 const cmd::Noop& args) { |
| 112 return parse_error::kParseNoError; | 155 return parse_error::kParseNoError; |
| 113 } | 156 } |
| 114 | 157 |
| 115 parse_error::ParseError CommonDecoder::HandleSetToken( | 158 parse_error::ParseError CommonDecoder::HandleSetToken( |
| 116 uint32 arg_count, | 159 uint32 immediate_data_size, |
| 117 const cmd::SetToken& args) { | 160 const cmd::SetToken& args) { |
| 118 engine_->set_token(args.token); | 161 engine_->set_token(args.token); |
| 119 return parse_error::kParseNoError; | 162 return parse_error::kParseNoError; |
| 120 } | 163 } |
| 121 | 164 |
| 122 parse_error::ParseError CommonDecoder::HandleJump( | 165 parse_error::ParseError CommonDecoder::HandleJump( |
| 123 uint32 arg_count, | 166 uint32 immediate_data_size, |
| 124 const cmd::Jump& args) { | 167 const cmd::Jump& args) { |
| 125 DCHECK(false); // TODO(gman): Implement. | 168 DCHECK(false); // TODO(gman): Implement. |
| 126 return parse_error::kParseNoError; | 169 return parse_error::kParseNoError; |
| 127 } | 170 } |
| 128 | 171 |
| 129 parse_error::ParseError CommonDecoder::HandleJumpRelative( | 172 parse_error::ParseError CommonDecoder::HandleJumpRelative( |
| 130 uint32 arg_count, | 173 uint32 immediate_data_size, |
| 131 const cmd::JumpRelative& args) { | 174 const cmd::JumpRelative& args) { |
| 132 DCHECK(false); // TODO(gman): Implement. | 175 DCHECK(false); // TODO(gman): Implement. |
| 133 return parse_error::kParseNoError; | 176 return parse_error::kParseNoError; |
| 134 } | 177 } |
| 135 | 178 |
| 136 parse_error::ParseError CommonDecoder::HandleCall( | 179 parse_error::ParseError CommonDecoder::HandleCall( |
| 137 uint32 arg_count, | 180 uint32 immediate_data_size, |
| 138 const cmd::Call& args) { | 181 const cmd::Call& args) { |
| 139 DCHECK(false); // TODO(gman): Implement. | 182 DCHECK(false); // TODO(gman): Implement. |
| 140 return parse_error::kParseNoError; | 183 return parse_error::kParseNoError; |
| 141 } | 184 } |
| 142 | 185 |
| 143 parse_error::ParseError CommonDecoder::HandleCallRelative( | 186 parse_error::ParseError CommonDecoder::HandleCallRelative( |
| 144 uint32 arg_count, | 187 uint32 immediate_data_size, |
| 145 const cmd::CallRelative& args) { | 188 const cmd::CallRelative& args) { |
| 146 DCHECK(false); // TODO(gman): Implement. | 189 DCHECK(false); // TODO(gman): Implement. |
| 147 return parse_error::kParseNoError; | 190 return parse_error::kParseNoError; |
| 148 } | 191 } |
| 149 | 192 |
| 150 parse_error::ParseError CommonDecoder::HandleReturn( | 193 parse_error::ParseError CommonDecoder::HandleReturn( |
| 151 uint32 arg_count, | 194 uint32 immediate_data_size, |
| 152 const cmd::Return& args) { | 195 const cmd::Return& args) { |
| 153 DCHECK(false); // TODO(gman): Implement. | 196 DCHECK(false); // TODO(gman): Implement. |
| 154 return parse_error::kParseNoError; | 197 return parse_error::kParseNoError; |
| 155 } | 198 } |
| 156 | 199 |
| 157 parse_error::ParseError CommonDecoder::HandleSetBucketSize( | 200 parse_error::ParseError CommonDecoder::HandleSetBucketSize( |
| 158 uint32 arg_count, | 201 uint32 immediate_data_size, |
| 159 const cmd::SetBucketSize& args) { | 202 const cmd::SetBucketSize& args) { |
| 160 DCHECK(false); // TODO(gman): Implement. | 203 uint32 bucket_id = args.bucket_id; |
| 204 uint32 size = args.size; |
| 205 |
| 206 Bucket* bucket = GetBucket(bucket_id); |
| 207 if (!bucket) { |
| 208 bucket = new Bucket(); |
| 209 buckets_[bucket_id] = linked_ptr<Bucket>(bucket); |
| 210 } |
| 211 |
| 212 bucket->SetSize(size); |
| 161 return parse_error::kParseNoError; | 213 return parse_error::kParseNoError; |
| 162 } | 214 } |
| 163 | 215 |
| 164 parse_error::ParseError CommonDecoder::HandleSetBucketData( | 216 parse_error::ParseError CommonDecoder::HandleSetBucketData( |
| 165 uint32 arg_count, | 217 uint32 immediate_data_size, |
| 166 const cmd::SetBucketData& args) { | 218 const cmd::SetBucketData& args) { |
| 167 DCHECK(false); // TODO(gman): Implement. | 219 uint32 bucket_id = args.bucket_id; |
| 220 uint32 offset = args.offset; |
| 221 uint32 size = args.size; |
| 222 const void* data = GetSharedMemoryAs<const void*>( |
| 223 args.shared_memory_id, args.shared_memory_offset, size); |
| 224 if (!data) { |
| 225 return parse_error::kParseInvalidArguments; |
| 226 } |
| 227 Bucket* bucket = GetBucket(bucket_id); |
| 228 if (!bucket) { |
| 229 return parse_error::kParseInvalidArguments; |
| 230 } |
| 231 if (!bucket->SetData(data, offset, size)) { |
| 232 return parse_error::kParseInvalidArguments; |
| 233 } |
| 234 |
| 168 return parse_error::kParseNoError; | 235 return parse_error::kParseNoError; |
| 169 } | 236 } |
| 170 | 237 |
| 171 parse_error::ParseError CommonDecoder::HandleSetBucketDataImmediate( | 238 parse_error::ParseError CommonDecoder::HandleSetBucketDataImmediate( |
| 172 uint32 arg_count, | 239 uint32 immediate_data_size, |
| 173 const cmd::SetBucketDataImmediate& args) { | 240 const cmd::SetBucketDataImmediate& args) { |
| 174 DCHECK(false); // TODO(gman): Implement. | 241 const void* data = GetImmediateDataAs<const void*>(args); |
| 242 uint32 bucket_id = args.bucket_id; |
| 243 uint32 offset = args.offset; |
| 244 uint32 size = args.size; |
| 245 if (size > immediate_data_size) { |
| 246 return parse_error::kParseInvalidArguments; |
| 247 } |
| 248 Bucket* bucket = GetBucket(bucket_id); |
| 249 if (!bucket) { |
| 250 return parse_error::kParseInvalidArguments; |
| 251 } |
| 252 if (!bucket->SetData(data, offset, size)) { |
| 253 return parse_error::kParseInvalidArguments; |
| 254 } |
| 175 return parse_error::kParseNoError; | 255 return parse_error::kParseNoError; |
| 176 } | 256 } |
| 177 | 257 |
| 178 parse_error::ParseError CommonDecoder::HandleGetResultSize( | 258 parse_error::ParseError CommonDecoder::HandleGetBucketSize( |
| 179 uint32 arg_count, | 259 uint32 immediate_data_size, |
| 180 const cmd::GetResultSize& args) { | 260 const cmd::GetBucketSize& args) { |
| 181 DCHECK(false); // TODO(gman): Implement. | 261 uint32 bucket_id = args.bucket_id; |
| 262 uint32* data = GetSharedMemoryAs<uint32*>( |
| 263 args.shared_memory_id, args.shared_memory_offset, sizeof(*data)); |
| 264 if (!data) { |
| 265 return parse_error::kParseInvalidArguments; |
| 266 } |
| 267 Bucket* bucket = GetBucket(bucket_id); |
| 268 if (!bucket) { |
| 269 return parse_error::kParseInvalidArguments; |
| 270 } |
| 271 *data = bucket->size(); |
| 182 return parse_error::kParseNoError; | 272 return parse_error::kParseNoError; |
| 183 } | 273 } |
| 184 | 274 |
| 185 parse_error::ParseError CommonDecoder::HandleGetResultData( | 275 parse_error::ParseError CommonDecoder::HandleGetBucketData( |
| 186 uint32 arg_count, | 276 uint32 immediate_data_size, |
| 187 const cmd::GetResultData& args) { | 277 const cmd::GetBucketData& args) { |
| 188 DCHECK(false); // TODO(gman): Implement. | 278 uint32 bucket_id = args.bucket_id; |
| 279 uint32 offset = args.offset; |
| 280 uint32 size = args.size; |
| 281 void* data = GetSharedMemoryAs<void*>( |
| 282 args.shared_memory_id, args.shared_memory_offset, size); |
| 283 if (!data) { |
| 284 return parse_error::kParseInvalidArguments; |
| 285 } |
| 286 Bucket* bucket = GetBucket(bucket_id); |
| 287 if (!bucket) { |
| 288 return parse_error::kParseInvalidArguments; |
| 289 } |
| 290 const void* src = bucket->GetData(offset, size); |
| 291 if (!src) { |
| 292 return parse_error::kParseInvalidArguments; |
| 293 } |
| 294 memcpy(data, src, size); |
| 189 return parse_error::kParseNoError; | 295 return parse_error::kParseNoError; |
| 190 } | 296 } |
| 191 | 297 |
| 192 } // namespace command_buffer | 298 } // namespace command_buffer |
| OLD | NEW |