Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / gpu / command_buffer / service / common_decoder_unittest.cc
blob11274e05f07a4267cad7df25fcd931be7a4daa53
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"
7 #include "testing/gtest/include/gtest/gtest.h"
9 namespace gpu {
11 TEST(CommonDecoderBucket, Basic) {
12 CommonDecoder::Bucket bucket;
13 EXPECT_EQ(0u, bucket.size());
14 EXPECT_TRUE(NULL == bucket.GetData(0, 0));
17 TEST(CommonDecoderBucket, Size) {
18 CommonDecoder::Bucket bucket;
19 bucket.SetSize(24);
20 EXPECT_EQ(24u, bucket.size());
21 bucket.SetSize(12);
22 EXPECT_EQ(12u, bucket.size());
25 TEST(CommonDecoderBucket, GetData) {
26 CommonDecoder::Bucket bucket;
28 bucket.SetSize(24);
29 EXPECT_TRUE(NULL != bucket.GetData(0, 0));
30 EXPECT_TRUE(NULL != bucket.GetData(24, 0));
31 EXPECT_TRUE(NULL == bucket.GetData(25, 0));
32 EXPECT_TRUE(NULL != bucket.GetData(0, 24));
33 EXPECT_TRUE(NULL == bucket.GetData(0, 25));
34 bucket.SetSize(23);
35 EXPECT_TRUE(NULL == bucket.GetData(0, 24));
38 TEST(CommonDecoderBucket, SetData) {
39 CommonDecoder::Bucket bucket;
40 static const char data[] = "testing";
42 bucket.SetSize(10);
43 EXPECT_TRUE(bucket.SetData(data, 0, sizeof(data)));
44 EXPECT_EQ(0, memcmp(data, bucket.GetData(0, sizeof(data)), sizeof(data)));
45 EXPECT_TRUE(bucket.SetData(data, 2, sizeof(data)));
46 EXPECT_EQ(0, memcmp(data, bucket.GetData(2, sizeof(data)), sizeof(data)));
47 EXPECT_FALSE(bucket.SetData(data, 0, sizeof(data) * 2));
48 EXPECT_FALSE(bucket.SetData(data, 5, sizeof(data)));
51 class TestCommonDecoder : public CommonDecoder {
52 public:
53 // Overridden from AsyncAPIInterface
54 virtual const char* GetCommandName(unsigned int command_id) const OVERRIDE {
55 return GetCommonCommandName(static_cast<cmd::CommandId>(command_id));
58 // Overridden from AsyncAPIInterface
59 virtual error::Error DoCommand(
60 unsigned int command,
61 unsigned int arg_count,
62 const void* cmd_data) OVERRIDE {
63 return DoCommonCommand(command, arg_count, cmd_data);
66 CommonDecoder::Bucket* GetBucket(uint32 id) const {
67 return CommonDecoder::GetBucket(id);
71 class MockCommandBufferEngine : public CommandBufferEngine {
72 public:
73 static const int32 kStartValidShmId = 1;
74 static const int32 kValidShmId = 2;
75 static const int32 kInvalidShmId = 3;
76 static const size_t kBufferSize = 1024;
77 static const int32 kValidOffset = kBufferSize / 2;
78 static const int32 kInvalidOffset = kBufferSize;
80 MockCommandBufferEngine()
81 : CommandBufferEngine(),
82 token_(),
83 get_offset_(0) {
84 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
85 shared_memory->CreateAndMapAnonymous(kBufferSize);
86 buffer_ = MakeBufferFromSharedMemory(shared_memory.Pass(), kBufferSize);
89 // Overridden from CommandBufferEngine.
90 virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
91 OVERRIDE {
92 if (IsValidSharedMemoryId(shm_id))
93 return buffer_;
94 return NULL;
97 template <typename T>
98 T GetSharedMemoryAs(uint32 offset) {
99 DCHECK_LT(offset, kBufferSize);
100 int8* buffer_memory = static_cast<int8*>(buffer_->memory());
101 return reinterpret_cast<T>(&buffer_memory[offset]);
104 int32 GetSharedMemoryOffset(const void* memory) {
105 int8* buffer_memory = static_cast<int8*>(buffer_->memory());
106 ptrdiff_t offset = static_cast<const int8*>(memory) - &buffer_memory[0];
107 DCHECK_GE(offset, 0);
108 DCHECK_LT(static_cast<size_t>(offset), kBufferSize);
109 return static_cast<int32>(offset);
112 // Overridden from CommandBufferEngine.
113 virtual void set_token(int32 token) OVERRIDE {
114 token_ = token;
117 int32 token() const {
118 return token_;
121 // Overridden from CommandBufferEngine.
122 virtual bool SetGetBuffer(int32 transfer_buffer_id) OVERRIDE {
123 NOTREACHED();
124 return false;
127 // Overridden from CommandBufferEngine.
128 virtual bool SetGetOffset(int32 offset) OVERRIDE {
129 if (static_cast<size_t>(offset) < kBufferSize) {
130 get_offset_ = offset;
131 return true;
133 return false;
136 // Overridden from CommandBufferEngine.
137 virtual int32 GetGetOffset() OVERRIDE {
138 return get_offset_;
141 private:
142 bool IsValidSharedMemoryId(int32 shm_id) {
143 return shm_id == kValidShmId || shm_id == kStartValidShmId;
146 scoped_refptr<gpu::Buffer> buffer_;
147 int32 token_;
148 int32 get_offset_;
151 const int32 MockCommandBufferEngine::kStartValidShmId;
152 const int32 MockCommandBufferEngine::kValidShmId;
153 const int32 MockCommandBufferEngine::kInvalidShmId;
154 const size_t MockCommandBufferEngine::kBufferSize;
155 const int32 MockCommandBufferEngine::kValidOffset;
156 const int32 MockCommandBufferEngine::kInvalidOffset;
158 class CommonDecoderTest : public testing::Test {
159 protected:
160 virtual void SetUp() {
161 decoder_.set_engine(&engine_);
164 virtual void TearDown() {
167 template <typename T>
168 error::Error ExecuteCmd(const T& cmd) {
169 COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
170 return decoder_.DoCommand(cmd.kCmdId,
171 ComputeNumEntries(sizeof(cmd)) - 1,
172 &cmd);
175 template <typename T>
176 error::Error ExecuteImmediateCmd(const T& cmd, size_t data_size) {
177 COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
178 return decoder_.DoCommand(cmd.kCmdId,
179 ComputeNumEntries(sizeof(cmd) + data_size) - 1,
180 &cmd);
183 MockCommandBufferEngine engine_;
184 TestCommonDecoder decoder_;
187 TEST_F(CommonDecoderTest, Initialize) {
188 EXPECT_EQ(0, engine_.GetGetOffset());
191 TEST_F(CommonDecoderTest, DoCommonCommandInvalidCommand) {
192 EXPECT_EQ(error::kUnknownCommand, decoder_.DoCommand(999999, 0, NULL));
195 TEST_F(CommonDecoderTest, HandleNoop) {
196 cmd::Noop cmd;
197 const uint32 kSkipCount = 5;
198 cmd.Init(kSkipCount);
199 EXPECT_EQ(error::kNoError,
200 ExecuteImmediateCmd(
201 cmd, kSkipCount * kCommandBufferEntrySize));
202 const uint32 kSkipCount2 = 1;
203 cmd.Init(kSkipCount2);
204 EXPECT_EQ(error::kNoError,
205 ExecuteImmediateCmd(
206 cmd, kSkipCount2 * kCommandBufferEntrySize));
209 TEST_F(CommonDecoderTest, SetToken) {
210 cmd::SetToken cmd;
211 const int32 kTokenId = 123;
212 EXPECT_EQ(0, engine_.token());
213 cmd.Init(kTokenId);
214 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
215 EXPECT_EQ(kTokenId, engine_.token());
218 TEST_F(CommonDecoderTest, SetBucketSize) {
219 cmd::SetBucketSize cmd;
220 const uint32 kBucketId = 123;
221 const uint32 kBucketLength1 = 1234;
222 const uint32 kBucketLength2 = 78;
223 // Check the bucket does not exist.
224 EXPECT_TRUE(NULL == decoder_.GetBucket(kBucketId));
225 // Check we can create one.
226 cmd.Init(kBucketId, kBucketLength1);
227 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
228 CommonDecoder::Bucket* bucket;
229 bucket = decoder_.GetBucket(kBucketId);
230 EXPECT_TRUE(NULL != bucket);
231 EXPECT_EQ(kBucketLength1, bucket->size());
232 // Check we can change it.
233 cmd.Init(kBucketId, kBucketLength2);
234 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
235 bucket = decoder_.GetBucket(kBucketId);
236 EXPECT_TRUE(NULL != bucket);
237 EXPECT_EQ(kBucketLength2, bucket->size());
238 // Check we can delete it.
239 cmd.Init(kBucketId, 0);
240 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
241 bucket = decoder_.GetBucket(kBucketId);
242 EXPECT_EQ(0u, bucket->size());
245 TEST_F(CommonDecoderTest, SetBucketData) {
246 cmd::SetBucketSize size_cmd;
247 cmd::SetBucketData cmd;
249 static const char kData[] = "1234567890123456789";
251 const uint32 kBucketId = 123;
252 const uint32 kInvalidBucketId = 124;
254 size_cmd.Init(kBucketId, sizeof(kData));
255 EXPECT_EQ(error::kNoError, ExecuteCmd(size_cmd));
256 CommonDecoder::Bucket* bucket = decoder_.GetBucket(kBucketId);
257 // Check the data is not there.
258 EXPECT_NE(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData)));
260 // Check we can set it.
261 const uint32 kSomeOffsetInSharedMemory = 50;
262 void* memory = engine_.GetSharedMemoryAs<void*>(kSomeOffsetInSharedMemory);
263 memcpy(memory, kData, sizeof(kData));
264 cmd.Init(kBucketId, 0, sizeof(kData),
265 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
266 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
267 EXPECT_EQ(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData)));
269 // Check we can set it partially.
270 static const char kData2[] = "ABCEDFG";
271 const uint32 kSomeOffsetInBucket = 5;
272 memcpy(memory, kData2, sizeof(kData2));
273 cmd.Init(kBucketId, kSomeOffsetInBucket, sizeof(kData2),
274 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
275 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
276 EXPECT_EQ(0, memcmp(bucket->GetData(kSomeOffsetInBucket, sizeof(kData2)),
277 kData2, sizeof(kData2)));
278 const char* bucket_data = bucket->GetDataAs<const char*>(0, sizeof(kData));
279 // Check that nothing was affected outside of updated area.
280 EXPECT_EQ(kData[kSomeOffsetInBucket - 1],
281 bucket_data[kSomeOffsetInBucket - 1]);
282 EXPECT_EQ(kData[kSomeOffsetInBucket + sizeof(kData2)],
283 bucket_data[kSomeOffsetInBucket + sizeof(kData2)]);
285 // Check that it fails if the bucket_id is invalid
286 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData2),
287 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
288 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
290 // Check that it fails if the offset is out of range.
291 cmd.Init(kBucketId, bucket->size(), 1,
292 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
293 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
295 // Check that it fails if the size is out of range.
296 cmd.Init(kBucketId, 0, bucket->size() + 1,
297 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
298 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
301 TEST_F(CommonDecoderTest, SetBucketDataImmediate) {
302 cmd::SetBucketSize size_cmd;
303 int8 buffer[1024];
304 cmd::SetBucketDataImmediate& cmd =
305 *reinterpret_cast<cmd::SetBucketDataImmediate*>(&buffer);
307 static const char kData[] = "1234567890123456789";
309 const uint32 kBucketId = 123;
310 const uint32 kInvalidBucketId = 124;
312 size_cmd.Init(kBucketId, sizeof(kData));
313 EXPECT_EQ(error::kNoError, ExecuteCmd(size_cmd));
314 CommonDecoder::Bucket* bucket = decoder_.GetBucket(kBucketId);
315 // Check the data is not there.
316 EXPECT_NE(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData)));
318 // Check we can set it.
319 void* memory = &buffer[0] + sizeof(cmd);
320 memcpy(memory, kData, sizeof(kData));
321 cmd.Init(kBucketId, 0, sizeof(kData));
322 EXPECT_EQ(error::kNoError,
323 ExecuteImmediateCmd(cmd, sizeof(kData)));
324 EXPECT_EQ(0, memcmp(bucket->GetData(0, sizeof(kData)), kData, sizeof(kData)));
326 // Check we can set it partially.
327 static const char kData2[] = "ABCEDFG";
328 const uint32 kSomeOffsetInBucket = 5;
329 memcpy(memory, kData2, sizeof(kData2));
330 cmd.Init(kBucketId, kSomeOffsetInBucket, sizeof(kData2));
331 EXPECT_EQ(error::kNoError,
332 ExecuteImmediateCmd(cmd, sizeof(kData2)));
333 EXPECT_EQ(0, memcmp(bucket->GetData(kSomeOffsetInBucket, sizeof(kData2)),
334 kData2, sizeof(kData2)));
335 const char* bucket_data = bucket->GetDataAs<const char*>(0, sizeof(kData));
336 // Check that nothing was affected outside of updated area.
337 EXPECT_EQ(kData[kSomeOffsetInBucket - 1],
338 bucket_data[kSomeOffsetInBucket - 1]);
339 EXPECT_EQ(kData[kSomeOffsetInBucket + sizeof(kData2)],
340 bucket_data[kSomeOffsetInBucket + sizeof(kData2)]);
342 // Check that it fails if the bucket_id is invalid
343 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData2));
344 EXPECT_NE(error::kNoError,
345 ExecuteImmediateCmd(cmd, sizeof(kData2)));
347 // Check that it fails if the offset is out of range.
348 cmd.Init(kBucketId, bucket->size(), 1);
349 EXPECT_NE(error::kNoError,
350 ExecuteImmediateCmd(cmd, sizeof(kData2)));
352 // Check that it fails if the size is out of range.
353 cmd.Init(kBucketId, 0, bucket->size() + 1);
354 EXPECT_NE(error::kNoError,
355 ExecuteImmediateCmd(cmd, sizeof(kData2)));
358 TEST_F(CommonDecoderTest, GetBucketStart) {
359 cmd::SetBucketSize size_cmd;
360 cmd::SetBucketData set_cmd;
361 cmd::GetBucketStart cmd;
363 static const char kData[] = "1234567890123456789";
364 static const char zero[sizeof(kData)] = { 0, };
366 const uint32 kBucketSize = sizeof(kData);
367 const uint32 kBucketId = 123;
368 const uint32 kInvalidBucketId = 124;
370 // Put data in the bucket.
371 size_cmd.Init(kBucketId, sizeof(kData));
372 EXPECT_EQ(error::kNoError, ExecuteCmd(size_cmd));
373 const uint32 kSomeOffsetInSharedMemory = 50;
374 uint8* start = engine_.GetSharedMemoryAs<uint8*>(kSomeOffsetInSharedMemory);
375 memcpy(start, kData, sizeof(kData));
376 set_cmd.Init(kBucketId, 0, sizeof(kData),
377 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
378 EXPECT_EQ(error::kNoError, ExecuteCmd(set_cmd));
380 // Check that the size is correct with no data buffer.
381 uint32* memory =
382 engine_.GetSharedMemoryAs<uint32*>(kSomeOffsetInSharedMemory);
383 *memory = 0x0;
384 cmd.Init(kBucketId,
385 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
386 0, 0, 0);
387 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
388 EXPECT_EQ(kBucketSize, *memory);
390 // Check that the data is copied with data buffer.
391 const uint32 kDataOffsetInSharedMemory = 54;
392 uint8* data = engine_.GetSharedMemoryAs<uint8*>(kDataOffsetInSharedMemory);
393 *memory = 0x0;
394 memset(data, 0, sizeof(kData));
395 cmd.Init(kBucketId,
396 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
397 kBucketSize, MockCommandBufferEngine::kValidShmId,
398 kDataOffsetInSharedMemory);
399 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
400 EXPECT_EQ(kBucketSize, *memory);
401 EXPECT_EQ(0, memcmp(data, kData, kBucketSize));
403 // Check that we can get a piece.
404 *memory = 0x0;
405 memset(data, 0, sizeof(kData));
406 const uint32 kPieceSize = kBucketSize / 2;
407 cmd.Init(kBucketId,
408 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
409 kPieceSize, MockCommandBufferEngine::kValidShmId,
410 kDataOffsetInSharedMemory);
411 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
412 EXPECT_EQ(kBucketSize, *memory);
413 EXPECT_EQ(0, memcmp(data, kData, kPieceSize));
414 EXPECT_EQ(0, memcmp(data + kPieceSize, zero, sizeof(kData) - kPieceSize));
416 // Check that it fails if the result_id is invalid
417 cmd.Init(kInvalidBucketId,
418 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
419 0, 0, 0);
420 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
422 // Check that it fails if the data_id is invalid
423 cmd.Init(kBucketId,
424 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
425 1, MockCommandBufferEngine::kInvalidShmId, 0);
426 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
428 // Check that it fails if the data_size is invalid
429 cmd.Init(kBucketId,
430 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
431 1, 0, 0);
432 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
433 cmd.Init(kBucketId,
434 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
435 MockCommandBufferEngine::kBufferSize + 1,
436 MockCommandBufferEngine::kValidShmId, 0);
437 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
439 // Check that it fails if the data_offset is invalid
440 cmd.Init(kBucketId,
441 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
442 0, 0, 1);
443 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
444 cmd.Init(kBucketId,
445 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
446 MockCommandBufferEngine::kBufferSize,
447 MockCommandBufferEngine::kValidShmId, 1);
448 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
450 // Check that it fails if the result size is not set to zero
451 *memory = 0x1;
452 cmd.Init(kBucketId,
453 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory,
454 0, 0, 0);
455 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
458 TEST_F(CommonDecoderTest, GetBucketData) {
459 cmd::SetBucketSize size_cmd;
460 cmd::SetBucketData set_cmd;
461 cmd::GetBucketData cmd;
463 static const char kData[] = "1234567890123456789";
464 static const char zero[sizeof(kData)] = { 0, };
466 const uint32 kBucketId = 123;
467 const uint32 kInvalidBucketId = 124;
469 size_cmd.Init(kBucketId, sizeof(kData));
470 EXPECT_EQ(error::kNoError, ExecuteCmd(size_cmd));
471 const uint32 kSomeOffsetInSharedMemory = 50;
472 uint8* memory = engine_.GetSharedMemoryAs<uint8*>(kSomeOffsetInSharedMemory);
473 memcpy(memory, kData, sizeof(kData));
474 set_cmd.Init(kBucketId, 0, sizeof(kData),
475 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
476 EXPECT_EQ(error::kNoError, ExecuteCmd(set_cmd));
478 // Check we can get the whole thing.
479 memset(memory, 0, sizeof(kData));
480 cmd.Init(kBucketId, 0, sizeof(kData),
481 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
482 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
483 EXPECT_EQ(0, memcmp(memory, kData, sizeof(kData)));
485 // Check we can get a piece.
486 const uint32 kSomeOffsetInBucket = 5;
487 const uint32 kLengthOfPiece = 6;
488 const uint8 kSentinel = 0xff;
489 memset(memory, 0, sizeof(kData));
490 memory[-1] = kSentinel;
491 cmd.Init(kBucketId, kSomeOffsetInBucket, kLengthOfPiece,
492 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
493 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
494 EXPECT_EQ(0, memcmp(memory, kData + kSomeOffsetInBucket, kLengthOfPiece));
495 EXPECT_EQ(0, memcmp(memory + kLengthOfPiece, zero,
496 sizeof(kData) - kLengthOfPiece));
497 EXPECT_EQ(kSentinel, memory[-1]);
499 // Check that it fails if the bucket_id is invalid
500 cmd.Init(kInvalidBucketId, kSomeOffsetInBucket, sizeof(kData),
501 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
502 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
504 // Check that it fails if the offset is invalid
505 cmd.Init(kBucketId, sizeof(kData) + 1, 1,
506 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
507 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
509 // Check that it fails if the size is invalid
510 cmd.Init(kBucketId, 0, sizeof(kData) + 1,
511 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory);
512 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
515 } // namespace gpu