OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/common_decoder.h" | 5 #include "gpu/command_buffer/service/common_decoder.h" |
6 #include "gpu/command_buffer/service/cmd_buffer_engine.h" | 6 #include "gpu/command_buffer/service/cmd_buffer_engine.h" |
7 #include "testing/gtest/include/gtest/gtest.h" | 7 #include "testing/gtest/include/gtest/gtest.h" |
8 | 8 |
9 namespace gpu { | 9 namespace gpu { |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 return DoCommonCommand(command, arg_count, cmd_data); | 63 return DoCommonCommand(command, arg_count, cmd_data); |
64 } | 64 } |
65 | 65 |
66 CommonDecoder::Bucket* GetBucket(uint32 id) const { | 66 CommonDecoder::Bucket* GetBucket(uint32 id) const { |
67 return CommonDecoder::GetBucket(id); | 67 return CommonDecoder::GetBucket(id); |
68 } | 68 } |
69 }; | 69 }; |
70 | 70 |
71 class MockCommandBufferEngine : public CommandBufferEngine { | 71 class MockCommandBufferEngine : public CommandBufferEngine { |
72 public: | 72 public: |
73 static const int32 kValidShmId = 1; | 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 uint32 kValidOffset = kBufferSize / 2; |
| 78 static const uint32 kInvalidOffset = kBufferSize; |
74 | 79 |
75 MockCommandBufferEngine() | 80 MockCommandBufferEngine() |
76 : CommandBufferEngine(), | 81 : CommandBufferEngine(), |
77 token_() { | 82 token_(), |
| 83 get_offset_(0) { |
78 } | 84 } |
79 | 85 |
80 // Overridden from CommandBufferEngine. | 86 // Overridden from CommandBufferEngine. |
81 virtual Buffer GetSharedMemoryBuffer(int32 shm_id) { | 87 virtual Buffer GetSharedMemoryBuffer(int32 shm_id) { |
82 Buffer buffer; | 88 Buffer buffer; |
83 if (shm_id == kValidShmId) { | 89 if (IsValidSharedMemoryId(shm_id)) { |
84 buffer.ptr = buffer_; | 90 buffer.ptr = buffer_; |
85 buffer.size = kBufferSize; | 91 buffer.size = kBufferSize; |
86 } | 92 } |
87 return buffer; | 93 return buffer; |
88 } | 94 } |
89 | 95 |
90 template <typename T> | 96 template <typename T> |
91 T GetSharedMemoryAs(uint32 offset) { | 97 T GetSharedMemoryAs(uint32 offset) { |
92 DCHECK(offset < kBufferSize); | 98 DCHECK(offset < kBufferSize); |
93 return reinterpret_cast<T>(&buffer_[offset]); | 99 return reinterpret_cast<T>(&buffer_[offset]); |
94 } | 100 } |
95 | 101 |
96 uint32 GetSharedMemoryOffset(const void* memory) { | 102 uint32 GetSharedMemoryOffset(const void* memory) { |
97 ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0]; | 103 ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0]; |
98 DCHECK(offset >= 0); | 104 DCHECK_GE(offset, 0); |
99 DCHECK(offset < kBufferSize); | 105 DCHECK(offset < kBufferSize); |
100 return static_cast<uint32>(offset); | 106 return static_cast<uint32>(offset); |
101 } | 107 } |
102 | 108 |
103 // Overridden from CommandBufferEngine. | 109 // Overridden from CommandBufferEngine. |
104 virtual void set_token(int32 token) { | 110 virtual void set_token(int32 token) { |
105 token_ = token; | 111 token_ = token; |
106 } | 112 } |
107 | 113 |
108 int32 token() const { | 114 int32 token() const { |
109 return token_; | 115 return token_; |
110 } | 116 } |
111 | 117 |
| 118 // Overridden from CommandBufferEngine. |
| 119 virtual bool SetGetOffset(int32 offset) { |
| 120 if (offset < kBufferSize) { |
| 121 get_offset_ = offset; |
| 122 return true; |
| 123 } |
| 124 return false; |
| 125 } |
| 126 |
| 127 // Overridden from CommandBufferEngine. |
| 128 virtual int32 GetGetOffset() { |
| 129 return get_offset_; |
| 130 } |
| 131 |
112 private: | 132 private: |
113 static const size_t kBufferSize = 1024; | 133 bool IsValidSharedMemoryId(int32 shm_id) { |
| 134 return shm_id == kValidShmId || shm_id == kStartValidShmId; |
| 135 } |
114 | 136 |
115 int8 buffer_[kBufferSize]; | 137 int8 buffer_[kBufferSize]; |
116 int32 token_; | 138 int32 token_; |
| 139 int32 get_offset_; |
117 }; | 140 }; |
118 | 141 |
119 class CommonDecoderTest : public testing::Test { | 142 class CommonDecoderTest : public testing::Test { |
120 protected: | 143 protected: |
121 virtual void SetUp() { | 144 virtual void SetUp() { |
122 decoder_.set_engine(&engine_); | 145 decoder_.set_engine(&engine_); |
123 } | 146 } |
124 | 147 |
125 virtual void TearDown() { | 148 virtual void TearDown() { |
126 } | 149 } |
(...skipping 11 matching lines...) Expand all Loading... |
138 COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN); | 161 COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN); |
139 return decoder_.DoCommand(cmd.kCmdId, | 162 return decoder_.DoCommand(cmd.kCmdId, |
140 ComputeNumEntries(sizeof(cmd) + data_size) - 1, | 163 ComputeNumEntries(sizeof(cmd) + data_size) - 1, |
141 &cmd); | 164 &cmd); |
142 } | 165 } |
143 | 166 |
144 MockCommandBufferEngine engine_; | 167 MockCommandBufferEngine engine_; |
145 TestCommonDecoder decoder_; | 168 TestCommonDecoder decoder_; |
146 }; | 169 }; |
147 | 170 |
| 171 TEST_F(CommonDecoderTest, Initialize) { |
| 172 EXPECT_EQ(0u, engine_.GetGetOffset()); |
| 173 } |
| 174 |
148 TEST_F(CommonDecoderTest, HandleNoop) { | 175 TEST_F(CommonDecoderTest, HandleNoop) { |
149 cmd::Noop cmd; | 176 cmd::Noop cmd; |
150 const uint32 kSkipCount = 5; | 177 const uint32 kSkipCount = 5; |
151 cmd.Init(kSkipCount); | 178 cmd.Init(kSkipCount); |
152 EXPECT_EQ(parse_error::kParseNoError, | 179 EXPECT_EQ(parse_error::kParseNoError, |
153 ExecuteImmediateCmd( | 180 ExecuteImmediateCmd( |
154 cmd, kSkipCount * kCommandBufferEntrySize)); | 181 cmd, kSkipCount * kCommandBufferEntrySize)); |
155 } | 182 } |
156 | 183 |
157 TEST_F(CommonDecoderTest, SetToken) { | 184 TEST_F(CommonDecoderTest, SetToken) { |
158 cmd::SetToken cmd; | 185 cmd::SetToken cmd; |
159 const int32 kTokenId = 123; | 186 const int32 kTokenId = 123; |
160 EXPECT_EQ(0, engine_.token()); | 187 EXPECT_EQ(0, engine_.token()); |
161 cmd.Init(kTokenId); | 188 cmd.Init(kTokenId); |
162 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); | 189 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
163 EXPECT_EQ(kTokenId, engine_.token()); | 190 EXPECT_EQ(kTokenId, engine_.token()); |
164 } | 191 } |
165 | 192 |
166 TEST_F(CommonDecoderTest, Jump) { | 193 TEST_F(CommonDecoderTest, Jump) { |
167 // cmd::Jump cmd; | 194 cmd::Jump cmd; |
168 // TODO(gman): implement. | 195 // Check valid args succeed. |
| 196 cmd.Init(MockCommandBufferEngine::kValidOffset); |
| 197 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 198 EXPECT_EQ(MockCommandBufferEngine::kValidOffset, |
| 199 engine_.GetGetOffset()); |
| 200 // Check invalid offset fails. |
| 201 cmd.Init(MockCommandBufferEngine::kInvalidOffset); |
| 202 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 203 EXPECT_EQ(MockCommandBufferEngine::kValidOffset, |
| 204 engine_.GetGetOffset()); |
169 } | 205 } |
170 | 206 |
| 207 // NOTE: The read_pointer checks for relative commands do not take into account |
| 208 // that the actual implementation of CommandBufferEngine uses the parse |
| 209 // which will advance the read pointer to the start of the next command. |
| 210 |
171 TEST_F(CommonDecoderTest, JumpRelative) { | 211 TEST_F(CommonDecoderTest, JumpRelative) { |
172 // cmd::JumpRelative cmd; | 212 cmd::JumpRelative cmd; |
173 // TODO(gman): implement. | 213 // Check valid positive offset succeeds. |
| 214 const int32 kPositiveOffset = 16; |
| 215 cmd.Init(kPositiveOffset); |
| 216 uint32 read_pointer = engine_.GetGetOffset(); |
| 217 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 218 // See note above. |
| 219 EXPECT_EQ(read_pointer + kPositiveOffset, engine_.GetGetOffset()); |
| 220 // Check valid negative offset succeeds. |
| 221 const int32 kNegativeOffset = -8; |
| 222 read_pointer = engine_.GetGetOffset(); |
| 223 cmd.Init(kNegativeOffset); |
| 224 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 225 // See note above. |
| 226 EXPECT_EQ(read_pointer + kNegativeOffset, engine_.GetGetOffset()); |
| 227 // Check invalid offset fails. |
| 228 cmd.Init(MockCommandBufferEngine::kInvalidOffset); |
| 229 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 230 // See note above. |
| 231 EXPECT_EQ(read_pointer + kNegativeOffset, engine_.GetGetOffset()); |
174 } | 232 } |
175 | 233 |
176 TEST_F(CommonDecoderTest, Call) { | 234 TEST_F(CommonDecoderTest, Call) { |
177 // cmd::Call cmd; | 235 cmd::Call cmd; |
178 // TODO(gman): implement. | 236 // Check valid args succeed. |
| 237 cmd.Init(MockCommandBufferEngine::kValidOffset); |
| 238 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 239 EXPECT_EQ(MockCommandBufferEngine::kValidOffset, |
| 240 engine_.GetGetOffset()); |
| 241 // Check invalid offset fails. |
| 242 cmd.Init(MockCommandBufferEngine::kInvalidOffset); |
| 243 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 244 EXPECT_EQ(MockCommandBufferEngine::kValidOffset, |
| 245 engine_.GetGetOffset()); |
| 246 // Check that the call values are on the stack. |
| 247 cmd::Return return_cmd; |
| 248 return_cmd.Init(); |
| 249 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); |
| 250 EXPECT_EQ(0u, engine_.GetGetOffset()); |
| 251 // Check that stack overflow fails. |
| 252 cmd.Init(MockCommandBufferEngine::kValidOffset); |
| 253 for (unsigned int ii = 0; ii < CommonDecoder::kMaxStackDepth; ++ii) { |
| 254 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 255 } |
| 256 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
179 } | 257 } |
180 | 258 |
181 TEST_F(CommonDecoderTest, CallRelative) { | 259 TEST_F(CommonDecoderTest, CallRelative) { |
182 // cmd::CallRelative cmd; | 260 cmd::CallRelative cmd; |
183 // TODO(gman): implement. | 261 // Check valid positive offset succeeds. |
| 262 const int32 kPositiveOffset = 16; |
| 263 cmd.Init(kPositiveOffset); |
| 264 uint32 read_pointer_1 = engine_.GetGetOffset(); |
| 265 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 266 // See note above. |
| 267 EXPECT_EQ(read_pointer_1 + kPositiveOffset, engine_.GetGetOffset()); |
| 268 // Check valid negative offset succeeds. |
| 269 const int32 kNegativeOffset = -8; |
| 270 uint32 read_pointer_2 = engine_.GetGetOffset(); |
| 271 cmd.Init(kNegativeOffset); |
| 272 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 273 // See note above. |
| 274 EXPECT_EQ(read_pointer_2 + kNegativeOffset, engine_.GetGetOffset()); |
| 275 // Check invalid offset fails. |
| 276 cmd.Init(MockCommandBufferEngine::kInvalidOffset); |
| 277 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 278 // See note above. |
| 279 EXPECT_EQ(read_pointer_2 + kNegativeOffset, engine_.GetGetOffset()); |
| 280 |
| 281 // Check that the call values are on the stack. |
| 282 cmd::Return return_cmd; |
| 283 return_cmd.Init(); |
| 284 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); |
| 285 // See note above. |
| 286 EXPECT_EQ(read_pointer_1 + kPositiveOffset, engine_.GetGetOffset()); |
| 287 |
| 288 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(return_cmd)); |
| 289 // See note above. |
| 290 EXPECT_EQ(0u, engine_.GetGetOffset()); |
| 291 // Check that stack overflow fails. |
| 292 cmd.Init(kPositiveOffset); |
| 293 for (unsigned int ii = 0; ii < CommonDecoder::kMaxStackDepth; ++ii) { |
| 294 EXPECT_EQ(parse_error::kParseNoError, ExecuteCmd(cmd)); |
| 295 } |
| 296 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
184 } | 297 } |
185 | 298 |
186 TEST_F(CommonDecoderTest, Return) { | 299 TEST_F(CommonDecoderTest, Return) { |
187 // cmd::Return cmd; | 300 // Success is tested by Call and CallRelative |
188 // TODO(gman): implement. | 301 // Test that an empty stack fails. |
| 302 cmd::Return cmd; |
| 303 cmd.Init(); |
| 304 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
189 } | 305 } |
190 | 306 |
191 TEST_F(CommonDecoderTest, SetBucketSize) { | 307 TEST_F(CommonDecoderTest, SetBucketSize) { |
192 cmd::SetBucketSize cmd; | 308 cmd::SetBucketSize cmd; |
193 const uint32 kBucketId = 123; | 309 const uint32 kBucketId = 123; |
194 const uint32 kBucketLength1 = 1234; | 310 const uint32 kBucketLength1 = 1234; |
195 const uint32 kBucketLength2 = 78; | 311 const uint32 kBucketLength2 = 78; |
196 // Check the bucket does not exist. | 312 // Check the bucket does not exist. |
197 EXPECT_TRUE(NULL == decoder_.GetBucket(kBucketId)); | 313 EXPECT_TRUE(NULL == decoder_.GetBucket(kBucketId)); |
198 // Check we can create one. | 314 // Check we can create one. |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 cmd.Init(kBucketId, sizeof(kData) + 1, 1, | 522 cmd.Init(kBucketId, sizeof(kData) + 1, 1, |
407 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); | 523 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
408 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); | 524 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
409 | 525 |
410 // Check that it fails if the size is invalid | 526 // Check that it fails if the size is invalid |
411 cmd.Init(kBucketId, 0, sizeof(kData) + 1, | 527 cmd.Init(kBucketId, 0, sizeof(kData) + 1, |
412 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); | 528 MockCommandBufferEngine::kValidShmId, kSomeOffsetInSharedMemory); |
413 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); | 529 EXPECT_NE(parse_error::kParseNoError, ExecuteCmd(cmd)); |
414 } | 530 } |
415 | 531 |
416 | |
417 } // namespace gpu | 532 } // namespace gpu |
418 | 533 |
OLD | NEW |