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"
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
;
21 void CommonDecoder::Bucket::SetSize(size_t size
) {
23 data_
.reset(size
? new int8
[size
] : NULL
);
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
);
38 void CommonDecoder::Bucket::SetFromString(const char* str
) {
39 // Strings are passed NULL terminated to distinguish between empty string
44 size_t size
= strlen(str
) + 1;
46 SetData(str
, 0, size
);
50 bool CommonDecoder::Bucket::GetAsString(std::string
* str
) {
55 str
->assign(GetDataAs
<const char*>(0, size_
- 1), size_
- 1);
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
) {
67 scoped_refptr
<gpu::Buffer
> buffer
= engine_
->GetSharedMemoryBuffer(shm_id
);
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
);
91 bucket
= new Bucket();
92 buckets_
[bucket_id
] = linked_ptr
<Bucket
>(bucket
);
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
113 // and gles2_cmd_decoder.cc. Fix it!
115 // A struct to hold info about each command.
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
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
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
);
202 return error::kInvalidArguments
;
204 Bucket
* bucket
= GetBucket(bucket_id
);
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
);
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
;
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
);
249 return error::kInvalidArguments
;
253 return error::kInvalidArguments
;
255 // Check that the client initialized the result.
257 return error::kInvalidArguments
;
259 Bucket
* bucket
= GetBucket(bucket_id
);
261 return error::kInvalidArguments
;
263 uint32 bucket_size
= bucket
->size();
264 *result
= bucket_size
;
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
);
281 return error::kInvalidArguments
;
283 Bucket
* bucket
= GetBucket(bucket_id
);
285 return error::kInvalidArguments
;
287 const void* src
= bucket
->GetData(offset
, size
);
289 return error::kInvalidArguments
;
291 memcpy(data
, src
, size
);
292 return error::kNoError
;