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 |