OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/at_exit.h" | 5 #include "base/at_exit.h" |
6 #include "base/message_loop.h" | 6 #include "base/message_loop.h" |
| 7 #include "o3d/command_buffer/common/cross/cmd_buffer_format.h" |
| 8 #include "o3d/command_buffer/service/cross/mocks.h" |
7 #include "o3d/gpu_plugin/command_buffer_mock.h" | 9 #include "o3d/gpu_plugin/command_buffer_mock.h" |
8 #include "o3d/gpu_plugin/gpu_processor.h" | 10 #include "o3d/gpu_plugin/gpu_processor.h" |
9 #include "o3d/gpu_plugin/np_utils/np_browser_stub.h" | 11 #include "o3d/gpu_plugin/np_utils/np_browser_stub.h" |
10 #include "o3d/gpu_plugin/np_utils/np_object_pointer.h" | 12 #include "o3d/gpu_plugin/np_utils/np_object_pointer.h" |
11 #include "o3d/gpu_plugin/system_services/shared_memory_mock.h" | 13 #include "o3d/gpu_plugin/system_services/shared_memory_mock.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
13 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
14 | 16 |
15 using testing::_; | 17 using testing::_; |
16 using testing::DoAll; | 18 using testing::DoAll; |
17 using testing::NiceMock; | 19 using testing::NiceMock; |
18 using testing::Return; | 20 using testing::Return; |
19 using testing::SetArgumentPointee; | 21 using testing::SetArgumentPointee; |
20 using testing::StrictMock; | 22 using testing::StrictMock; |
21 | 23 |
22 namespace o3d { | 24 namespace o3d { |
23 namespace gpu_plugin { | 25 namespace gpu_plugin { |
24 | 26 |
25 class GPUProcessorTest : public testing::Test { | 27 class GPUProcessorTest : public testing::Test { |
26 protected: | 28 protected: |
27 virtual void SetUp() { | 29 virtual void SetUp() { |
28 shared_memory_ = NPCreateObject<NiceMock<MockSharedMemory> >(NULL); | 30 shared_memory_ = NPCreateObject<NiceMock<MockSharedMemory> >(NULL); |
29 shared_memory_->ptr = buffer_; | 31 shared_memory_->ptr = buffer_; |
30 shared_memory_->size = sizeof(buffer_); | 32 shared_memory_->size = sizeof(buffer_); |
31 memset(buffer_, 0, sizeof(buffer_)); | 33 memset(buffer_, 0, sizeof(buffer_)); |
32 | 34 |
33 command_buffer_ = NPCreateObject<MockCommandBuffer>(NULL); | 35 command_buffer_ = NPCreateObject<MockCommandBuffer>(NULL); |
34 ON_CALL(*command_buffer_.Get(), GetRingBuffer()) | 36 ON_CALL(*command_buffer_.Get(), GetRingBuffer()) |
35 .WillByDefault(Return(shared_memory_)); | 37 .WillByDefault(Return(shared_memory_)); |
| 38 ON_CALL(*command_buffer_.Get(), GetSize()) |
| 39 .WillByDefault(Return(sizeof(buffer_))); |
36 | 40 |
37 processor_ = new GPUProcessor(command_buffer_); | 41 #if defined(OS_WIN) |
| 42 gapi_ = new command_buffer::GAPID3D9; |
| 43 #endif |
| 44 |
| 45 async_api_.reset(new StrictMock<command_buffer::AsyncAPIMock>); |
| 46 |
| 47 decoder_ = new command_buffer::GAPIDecoder(gapi_); |
| 48 |
| 49 parser_ = new command_buffer::CommandParser(buffer_, |
| 50 sizeof(buffer_), |
| 51 0, |
| 52 sizeof(buffer_), |
| 53 0, |
| 54 async_api_.get()); |
| 55 |
| 56 processor_ = new GPUProcessor(NULL, |
| 57 command_buffer_, |
| 58 gapi_, |
| 59 decoder_, |
| 60 parser_, |
| 61 2); |
38 } | 62 } |
39 | 63 |
40 virtual void TearDown() { | 64 virtual void TearDown() { |
41 // Ensure that any unexpected tasks posted by the GPU processor are executed | 65 // Ensure that any unexpected tasks posted by the GPU processor are executed |
42 // in order to fail the test. | 66 // in order to fail the test. |
43 MessageLoop::current()->RunAllPending(); | 67 MessageLoop::current()->RunAllPending(); |
44 } | 68 } |
45 | 69 |
46 base::AtExitManager at_exit_manager; | 70 base::AtExitManager at_exit_manager; |
47 MessageLoop message_loop; | 71 MessageLoop message_loop; |
48 StubNPBrowser stub_browser_; | 72 StubNPBrowser stub_browser_; |
49 NPObjectPointer<MockCommandBuffer> command_buffer_; | 73 NPObjectPointer<MockCommandBuffer> command_buffer_; |
50 NPObjectPointer<NiceMock<MockSharedMemory> > shared_memory_; | 74 NPObjectPointer<NiceMock<MockSharedMemory> > shared_memory_; |
51 int32 buffer_[1024 / sizeof(int32)]; | 75 int32 buffer_[1024 / sizeof(int32)]; |
| 76 command_buffer::GAPIDecoder* decoder_; |
| 77 command_buffer::CommandParser* parser_; |
| 78 scoped_ptr<command_buffer::AsyncAPIMock> async_api_; |
52 scoped_refptr<GPUProcessor> processor_; | 79 scoped_refptr<GPUProcessor> processor_; |
| 80 |
| 81 #if defined(OS_WIN) |
| 82 command_buffer::GAPID3D9* gapi_; |
| 83 #endif |
53 }; | 84 }; |
54 | 85 |
55 TEST_F(GPUProcessorTest, ProcessorDoesNothingIfNoSharedMemory) { | 86 TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) { |
56 EXPECT_CALL(*command_buffer_, GetGetOffset()) | 87 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
57 .WillOnce(Return(0)); | 88 .WillOnce(Return(0)); |
58 EXPECT_CALL(*command_buffer_, GetPutOffset()) | 89 EXPECT_CALL(*command_buffer_, SetGetOffset(0)); |
59 .WillOnce(Return(0)); | 90 |
60 EXPECT_CALL(*command_buffer_, GetSize()) | 91 processor_->ProcessCommands(); |
61 .WillOnce(Return(1024)); | 92 |
62 ON_CALL(*command_buffer_.Get(), GetRingBuffer()) | 93 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_NO_ERROR, |
63 .WillByDefault(Return(NPObjectPointer<CHRSharedMemory>())); | 94 command_buffer_->ResetParseError()); |
64 | 95 EXPECT_FALSE(command_buffer_->GetErrorStatus()); |
65 processor_->ProcessCommands(); | 96 } |
66 } | 97 |
67 | 98 TEST_F(GPUProcessorTest, ProcessesOneCommand) { |
68 TEST_F(GPUProcessorTest, ProcessorDoesNothingIfSharedMemoryIsUnmapped) { | 99 command_buffer::CommandHeader* header = |
69 EXPECT_CALL(*command_buffer_, GetGetOffset()) | 100 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
70 .WillOnce(Return(0)); | 101 header[0].command = 7; |
71 EXPECT_CALL(*command_buffer_, GetPutOffset()) | 102 header[0].size = 2; |
72 .WillOnce(Return(0)); | 103 buffer_[1] = 123; |
73 EXPECT_CALL(*command_buffer_, GetSize()) | 104 |
74 .WillOnce(Return(1024)); | 105 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 106 .WillOnce(Return(2)); |
| 107 EXPECT_CALL(*command_buffer_, SetGetOffset(2)); |
| 108 |
| 109 EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[1])) |
| 110 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 111 |
| 112 processor_->ProcessCommands(); |
| 113 |
| 114 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_NO_ERROR, |
| 115 command_buffer_->ResetParseError()); |
| 116 EXPECT_FALSE(command_buffer_->GetErrorStatus()); |
| 117 } |
| 118 |
| 119 TEST_F(GPUProcessorTest, ProcessesTwoCommands) { |
| 120 command_buffer::CommandHeader* header = |
| 121 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 122 header[0].command = 7; |
| 123 header[0].size = 2; |
| 124 buffer_[1] = 123; |
| 125 header[2].command = 8; |
| 126 header[2].size = 1; |
| 127 |
| 128 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 129 .WillOnce(Return(3)); |
| 130 EXPECT_CALL(*command_buffer_, SetGetOffset(3)); |
| 131 |
| 132 EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[1])) |
| 133 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 134 |
| 135 EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[3])) |
| 136 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 137 |
| 138 processor_->ProcessCommands(); |
| 139 } |
| 140 |
| 141 TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) { |
| 142 command_buffer::CommandHeader* header = |
| 143 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 144 header[0].command = 7; |
| 145 header[0].size = 2; |
| 146 buffer_[1] = 123; |
| 147 header[2].command = 8; |
| 148 header[2].size = 1; |
| 149 header[3].command = 9; |
| 150 header[3].size = 1; |
| 151 |
| 152 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 153 .WillOnce(Return(4)); |
| 154 |
| 155 EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[1])) |
| 156 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 157 |
| 158 EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[3])) |
| 159 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 160 |
| 161 EXPECT_CALL(*command_buffer_, SetGetOffset(3)); |
| 162 |
| 163 processor_->ProcessCommands(); |
| 164 |
| 165 // ProcessCommands is called a second time when the pending task is run. |
| 166 |
| 167 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 168 .WillOnce(Return(4)); |
| 169 |
| 170 EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[4])) |
| 171 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 172 |
| 173 EXPECT_CALL(*command_buffer_, SetGetOffset(4)); |
| 174 |
| 175 MessageLoop::current()->RunAllPending(); |
| 176 } |
| 177 |
| 178 TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) { |
| 179 command_buffer::CommandHeader* header = |
| 180 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 181 header[0].command = 7; |
| 182 header[0].size = 1; |
| 183 |
| 184 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 185 .WillOnce(Return(1)); |
| 186 EXPECT_CALL(*command_buffer_, SetGetOffset(1)); |
| 187 |
| 188 EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[1])) |
| 189 .WillOnce(Return( |
| 190 command_buffer::BufferSyncInterface::PARSE_UNKNOWN_COMMAND)); |
| 191 |
| 192 processor_->ProcessCommands(); |
| 193 |
| 194 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_UNKNOWN_COMMAND, |
| 195 command_buffer_->ResetParseError()); |
| 196 EXPECT_FALSE(command_buffer_->GetErrorStatus()); |
| 197 } |
| 198 |
| 199 TEST_F(GPUProcessorTest, |
| 200 RecoverableParseErrorsAreNotClearedByFollowingSuccessfulCommands) { |
| 201 command_buffer::CommandHeader* header = |
| 202 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 203 header[0].command = 7; |
| 204 header[0].size = 1; |
| 205 header[1].command = 8; |
| 206 header[1].size = 1; |
| 207 |
| 208 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 209 .WillOnce(Return(2)); |
| 210 EXPECT_CALL(*command_buffer_, SetGetOffset(2)); |
| 211 |
| 212 EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[1])) |
| 213 .WillOnce(Return( |
| 214 command_buffer::BufferSyncInterface::PARSE_UNKNOWN_COMMAND)); |
| 215 |
| 216 EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2])) |
| 217 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_NO_ERROR)); |
| 218 |
| 219 processor_->ProcessCommands(); |
| 220 |
| 221 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_UNKNOWN_COMMAND, |
| 222 command_buffer_->ResetParseError()); |
| 223 EXPECT_FALSE(command_buffer_->GetErrorStatus()); |
| 224 } |
| 225 |
| 226 TEST_F(GPUProcessorTest, UnrecoverableParseErrorsRaiseTheErrorStatus) { |
| 227 command_buffer::CommandHeader* header = |
| 228 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 229 header[0].command = 7; |
| 230 header[0].size = 1; |
| 231 header[1].command = 8; |
| 232 header[1].size = 1; |
| 233 |
| 234 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 235 .WillOnce(Return(2)); |
| 236 |
| 237 EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[1])) |
| 238 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_INVALID_SIZE)); |
| 239 |
| 240 processor_->ProcessCommands(); |
| 241 |
| 242 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_INVALID_SIZE, |
| 243 command_buffer_->ResetParseError()); |
| 244 EXPECT_TRUE(command_buffer_->GetErrorStatus()); |
| 245 } |
| 246 |
| 247 TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterUnrecoverableError) { |
| 248 command_buffer::CommandHeader* header = |
| 249 reinterpret_cast<command_buffer::CommandHeader*>(&buffer_[0]); |
| 250 header[0].command = 7; |
| 251 header[0].size = 1; |
| 252 header[1].command = 8; |
| 253 header[1].size = 1; |
| 254 |
| 255 EXPECT_CALL(*command_buffer_, GetPutOffset()) |
| 256 .WillOnce(Return(2)); |
| 257 |
| 258 EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[1])) |
| 259 .WillOnce(Return(command_buffer::BufferSyncInterface::PARSE_INVALID_SIZE)); |
| 260 |
| 261 processor_->ProcessCommands(); |
| 262 processor_->ProcessCommands(); |
| 263 |
| 264 EXPECT_EQ(command_buffer::BufferSyncInterface::PARSE_INVALID_SIZE, |
| 265 command_buffer_->ResetParseError()); |
| 266 EXPECT_TRUE(command_buffer_->GetErrorStatus()); |
| 267 } |
| 268 |
| 269 TEST_F(GPUProcessorTest, CanGetAddressOfSharedMemory) { |
| 270 EXPECT_CALL(*command_buffer_.Get(), GetRegisteredObject(7)) |
| 271 .WillOnce(Return(shared_memory_)); |
| 272 |
| 273 EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7)); |
| 274 } |
| 275 |
| 276 ACTION_P2(SetPointee, address, value) { |
| 277 *address = value; |
| 278 } |
| 279 |
| 280 TEST_F(GPUProcessorTest, GetAddressOfSharedMemoryMapsMemoryIfUnmapped) { |
| 281 EXPECT_CALL(*command_buffer_.Get(), GetRegisteredObject(7)) |
| 282 .WillOnce(Return(shared_memory_)); |
| 283 |
75 shared_memory_->ptr = NULL; | 284 shared_memory_->ptr = NULL; |
76 | 285 |
77 processor_->ProcessCommands(); | 286 EXPECT_CALL(*shared_memory_.Get(), Map()) |
78 } | 287 .WillOnce(DoAll(SetPointee(&shared_memory_->ptr, &buffer_[0]), |
79 | 288 Return(true))); |
80 TEST_F(GPUProcessorTest, ProcessorDoesNothingIfCommandBufferIsZeroSize) { | 289 |
81 EXPECT_CALL(*command_buffer_, GetGetOffset()) | 290 EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryAddress(7)); |
82 .WillOnce(Return(0)); | 291 } |
83 EXPECT_CALL(*command_buffer_, GetPutOffset()) | 292 |
84 .WillOnce(Return(0)); | 293 TEST_F(GPUProcessorTest, CanGetSizeOfSharedMemory) { |
85 EXPECT_CALL(*command_buffer_, GetSize()) | 294 EXPECT_CALL(*command_buffer_.Get(), GetRegisteredObject(7)) |
86 .WillOnce(Return(0)); | 295 .WillOnce(Return(shared_memory_)); |
87 | 296 |
88 processor_->ProcessCommands(); | 297 EXPECT_EQ(sizeof(buffer_), processor_->GetSharedMemorySize(7)); |
89 } | 298 } |
90 | 299 |
91 TEST_F(GPUProcessorTest, ProcessorDoesNothingIfCommandBufferIsEmpty) { | 300 TEST_F(GPUProcessorTest, SetTokenForwardsToCommandBuffer) { |
92 EXPECT_CALL(*command_buffer_, GetGetOffset()) | 301 processor_->set_token(7); |
93 .WillOnce(Return(0)); | 302 EXPECT_EQ(7, command_buffer_->GetToken()); |
94 EXPECT_CALL(*command_buffer_, GetPutOffset()) | |
95 .WillOnce(Return(0)); | |
96 EXPECT_CALL(*command_buffer_, GetSize()) | |
97 .WillOnce(Return(sizeof(buffer_))); | |
98 | |
99 processor_->ProcessCommands(); | |
100 } | |
101 | |
102 TEST_F(GPUProcessorTest, ProcessorHandlesSingleNopCommand) { | |
103 EXPECT_CALL(*command_buffer_, GetGetOffset()) | |
104 .WillOnce(Return(0)); | |
105 EXPECT_CALL(*command_buffer_, GetPutOffset()) | |
106 .WillOnce(Return(4)); | |
107 EXPECT_CALL(*command_buffer_, GetSize()) | |
108 .WillOnce(Return(sizeof(buffer_))); | |
109 EXPECT_CALL(*command_buffer_, SetGetOffset(4)); | |
110 | |
111 processor_->ProcessCommands(); | |
112 } | |
113 | |
114 TEST_F(GPUProcessorTest, ProcessorWrapsAroundToBeginningOfCommandBuffer) { | |
115 EXPECT_CALL(*command_buffer_, GetGetOffset()) | |
116 .WillOnce(Return(4)); | |
117 EXPECT_CALL(*command_buffer_, GetPutOffset()) | |
118 .WillOnce(Return(0)); | |
119 EXPECT_CALL(*command_buffer_, GetSize()) | |
120 .WillOnce(Return(8)); | |
121 EXPECT_CALL(*command_buffer_, SetGetOffset(0)); | |
122 | |
123 processor_->ProcessCommands(); | |
124 } | |
125 | |
126 TEST_F(GPUProcessorTest, | |
127 ProcessorHandlesSingleCommandAndPostsTaskToProcessAdditionalCommands) { | |
128 EXPECT_CALL(*command_buffer_, GetGetOffset()) | |
129 .WillOnce(Return(0)) | |
130 .WillOnce(Return(4)); | |
131 EXPECT_CALL(*command_buffer_, GetPutOffset()) | |
132 .WillOnce(Return(8)) | |
133 .WillOnce(Return(8)); | |
134 EXPECT_CALL(*command_buffer_, GetSize()) | |
135 .WillOnce(Return(sizeof(buffer_))) | |
136 .WillOnce(Return(sizeof(buffer_))); | |
137 EXPECT_CALL(*command_buffer_, SetGetOffset(4)); | |
138 | |
139 processor_->ProcessCommands(); | |
140 | |
141 EXPECT_CALL(*command_buffer_, SetGetOffset(8)); | |
142 MessageLoop::current()->RunAllPending(); | |
143 } | |
144 | |
145 TEST_F(GPUProcessorTest, ProcessorDoesNotImmediatelyHandlePartialCommands) { | |
146 EXPECT_CALL(*command_buffer_, GetGetOffset()) | |
147 .WillOnce(Return(0)) | |
148 .WillOnce(Return(0)); | |
149 EXPECT_CALL(*command_buffer_, GetPutOffset()) | |
150 .WillOnce(Return(2)) | |
151 .WillOnce(Return(4)); | |
152 EXPECT_CALL(*command_buffer_, GetSize()) | |
153 .WillOnce(Return(sizeof(buffer_))) | |
154 .WillOnce(Return(sizeof(buffer_))); | |
155 | |
156 processor_->ProcessCommands(); | |
157 | |
158 EXPECT_CALL(*command_buffer_, SetGetOffset(4)); | |
159 MessageLoop::current()->RunAllPending(); | |
160 } | 303 } |
161 | 304 |
162 } // namespace gpu_plugin | 305 } // namespace gpu_plugin |
163 } // namespace o3d | 306 } // namespace o3d |
OLD | NEW |