OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // Tests for the Command Buffer Helper. | 5 // Tests for the Command Buffer Helper. |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "gpu/command_buffer/client/cmd_buffer_helper.h" | 10 #include "gpu/command_buffer/client/cmd_buffer_helper.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 const int32 kUnusedCommandId = 5; // we use 0 and 2 currently. | 34 const int32 kUnusedCommandId = 5; // we use 0 and 2 currently. |
35 | 35 |
36 // Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper, | 36 // Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper, |
37 // using a CommandBufferEngine with a mock AsyncAPIInterface for its interface | 37 // using a CommandBufferEngine with a mock AsyncAPIInterface for its interface |
38 // (calling it directly, not through the RPC mechanism). | 38 // (calling it directly, not through the RPC mechanism). |
39 class CommandBufferHelperTest : public testing::Test { | 39 class CommandBufferHelperTest : public testing::Test { |
40 protected: | 40 protected: |
41 // Helper so mock can handle the Jump command. | 41 // Helper so mock can handle the Jump command. |
42 class DoJumpCommand { | 42 class DoJumpCommand { |
43 public: | 43 public: |
44 explicit DoJumpCommand(CommandParser* parser) | 44 explicit DoJumpCommand(GpuScheduler* gpu_scheduler) |
45 : parser_(parser) { | 45 : gpu_scheduler_(gpu_scheduler) { |
46 } | 46 } |
47 | 47 |
48 error::Error DoCommand( | 48 error::Error DoCommand( |
49 unsigned int command, | 49 unsigned int command, |
50 unsigned int arg_count, | 50 unsigned int arg_count, |
51 const void* cmd_data) { | 51 const void* cmd_data) { |
52 const cmd::Jump* jump_cmd = static_cast<const cmd::Jump*>(cmd_data); | 52 const cmd::Jump* jump_cmd = static_cast<const cmd::Jump*>(cmd_data); |
53 parser_->set_get(jump_cmd->offset); | 53 gpu_scheduler_->parser()->set_get(jump_cmd->offset); |
54 return error::kNoError; | 54 return error::kNoError; |
55 }; | 55 }; |
56 | 56 |
57 private: | 57 private: |
58 CommandParser* parser_; | 58 GpuScheduler* gpu_scheduler_; |
59 }; | 59 }; |
60 | 60 |
61 virtual void SetUp() { | 61 virtual void SetUp() { |
62 api_mock_.reset(new AsyncAPIMock); | 62 api_mock_.reset(new AsyncAPIMock); |
63 // ignore noops in the mock - we don't want to inspect the internals of the | 63 // ignore noops in the mock - we don't want to inspect the internals of the |
64 // helper. | 64 // helper. |
65 EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, _, _)) | 65 EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, _, _)) |
66 .WillRepeatedly(Return(error::kNoError)); | 66 .WillRepeatedly(Return(error::kNoError)); |
67 | 67 |
68 command_buffer_.reset(new CommandBufferService); | 68 command_buffer_.reset(new CommandBufferService); |
69 command_buffer_->Initialize(); | 69 command_buffer_->Initialize(); |
70 | 70 |
71 parser_ = new CommandParser(api_mock_.get()); | 71 gpu_scheduler_.reset(new GpuScheduler( |
| 72 command_buffer_.get(), api_mock_.get(), NULL)); |
| 73 command_buffer_->SetPutOffsetChangeCallback(base::Bind( |
| 74 &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); |
| 75 command_buffer_->SetGetBufferChangeCallback(base::Bind( |
| 76 &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get()))); |
72 | 77 |
73 do_jump_command_.reset(new DoJumpCommand(parser_)); | 78 do_jump_command_.reset(new DoJumpCommand(gpu_scheduler_.get())); |
74 EXPECT_CALL(*api_mock_, DoCommand(cmd::kJump, _, _)) | 79 EXPECT_CALL(*api_mock_, DoCommand(cmd::kJump, _, _)) |
75 .WillRepeatedly( | 80 .WillRepeatedly( |
76 Invoke(do_jump_command_.get(), &DoJumpCommand::DoCommand)); | 81 Invoke(do_jump_command_.get(), &DoJumpCommand::DoCommand)); |
77 | 82 |
78 gpu_scheduler_.reset(new GpuScheduler( | |
79 command_buffer_.get(), NULL, parser_)); | |
80 command_buffer_->SetPutOffsetChangeCallback(base::Bind( | |
81 &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get()))); | |
82 | 83 |
83 api_mock_->set_engine(gpu_scheduler_.get()); | 84 api_mock_->set_engine(gpu_scheduler_.get()); |
84 | 85 |
85 helper_.reset(new CommandBufferHelper(command_buffer_.get())); | 86 helper_.reset(new CommandBufferHelper(command_buffer_.get())); |
86 helper_->Initialize(kCommandBufferSizeBytes); | 87 helper_->Initialize(kCommandBufferSizeBytes); |
87 | |
88 // Note: parser->SetBuffer would normally be called through | |
89 // helper_->Initialize but currently it needs a GpuCommandBufferStub as the | |
90 // CommandBuffer instead of the CommandBufferService for that to happen. | |
91 Buffer ring_buffer = helper_->get_ring_buffer(); | |
92 parser_->SetBuffer(ring_buffer.ptr, ring_buffer.size, 0, ring_buffer.size); | |
93 } | 88 } |
94 | 89 |
95 virtual void TearDown() { | 90 virtual void TearDown() { |
96 // If the GpuScheduler posts any tasks, this forces them to run. | 91 // If the GpuScheduler posts any tasks, this forces them to run. |
97 MessageLoop::current()->RunAllPending(); | 92 MessageLoop::current()->RunAllPending(); |
98 } | 93 } |
99 | 94 |
| 95 const CommandParser* GetParser() const { |
| 96 return gpu_scheduler_->parser(); |
| 97 } |
| 98 |
100 // Adds a command to the buffer through the helper, while adding it as an | 99 // Adds a command to the buffer through the helper, while adding it as an |
101 // expected call on the API mock. | 100 // expected call on the API mock. |
102 void AddCommandWithExpect(error::Error _return, | 101 void AddCommandWithExpect(error::Error _return, |
103 unsigned int command, | 102 unsigned int command, |
104 int arg_count, | 103 int arg_count, |
105 CommandBufferEntry *args) { | 104 CommandBufferEntry *args) { |
106 CommandHeader header; | 105 CommandHeader header; |
107 header.size = arg_count + 1; | 106 header.size = arg_count + 1; |
108 header.command = command; | 107 header.command = command; |
109 CommandBufferEntry* cmds = helper_->GetSpace(arg_count + 1); | 108 CommandBufferEntry* cmds = helper_->GetSpace(arg_count + 1); |
110 CommandBufferOffset put = 0; | 109 CommandBufferOffset put = 0; |
111 cmds[put++].value_header = header; | 110 cmds[put++].value_header = header; |
112 for (int ii = 0; ii < arg_count; ++ii) { | 111 for (int ii = 0; ii < arg_count; ++ii) { |
113 cmds[put++] = args[ii]; | 112 cmds[put++] = args[ii]; |
114 } | 113 } |
115 | 114 |
116 EXPECT_CALL(*api_mock_, DoCommand(command, arg_count, | 115 EXPECT_CALL(*api_mock_, DoCommand(command, arg_count, |
117 Truly(AsyncAPIMock::IsArgs(arg_count, args)))) | 116 Truly(AsyncAPIMock::IsArgs(arg_count, args)))) |
118 .InSequence(sequence_) | 117 .InSequence(sequence_) |
119 .WillOnce(Return(_return)); | 118 .WillOnce(Return(_return)); |
120 } | 119 } |
121 | 120 |
122 // Checks that the buffer from put to put+size is free in the parser. | 121 // Checks that the buffer from put to put+size is free in the parser. |
123 void CheckFreeSpace(CommandBufferOffset put, unsigned int size) { | 122 void CheckFreeSpace(CommandBufferOffset put, unsigned int size) { |
124 CommandBufferOffset parser_put = parser_->put(); | 123 CommandBufferOffset parser_put = GetParser()->put(); |
125 CommandBufferOffset parser_get = parser_->get(); | 124 CommandBufferOffset parser_get = GetParser()->get(); |
126 CommandBufferOffset limit = put + size; | 125 CommandBufferOffset limit = put + size; |
127 if (parser_get > parser_put) { | 126 if (parser_get > parser_put) { |
128 // "busy" buffer wraps, so "free" buffer is between put (inclusive) and | 127 // "busy" buffer wraps, so "free" buffer is between put (inclusive) and |
129 // get (exclusive). | 128 // get (exclusive). |
130 EXPECT_LE(parser_put, put); | 129 EXPECT_LE(parser_put, put); |
131 EXPECT_GT(parser_get, limit); | 130 EXPECT_GT(parser_get, limit); |
132 } else { | 131 } else { |
133 // "busy" buffer does not wrap, so the "free" buffer is the top side (from | 132 // "busy" buffer does not wrap, so the "free" buffer is the top side (from |
134 // put to the limit) and the bottom side (from 0 to get). | 133 // put to the limit) and the bottom side (from 0 to get). |
135 if (put >= parser_put) { | 134 if (put >= parser_put) { |
(...skipping 20 matching lines...) Expand all Loading... |
156 | 155 |
157 CommandBufferOffset get_helper_put() { return helper_->put_; } | 156 CommandBufferOffset get_helper_put() { return helper_->put_; } |
158 | 157 |
159 #if defined(OS_MACOSX) | 158 #if defined(OS_MACOSX) |
160 base::mac::ScopedNSAutoreleasePool autorelease_pool_; | 159 base::mac::ScopedNSAutoreleasePool autorelease_pool_; |
161 #endif | 160 #endif |
162 MessageLoop message_loop_; | 161 MessageLoop message_loop_; |
163 scoped_ptr<AsyncAPIMock> api_mock_; | 162 scoped_ptr<AsyncAPIMock> api_mock_; |
164 scoped_ptr<CommandBufferService> command_buffer_; | 163 scoped_ptr<CommandBufferService> command_buffer_; |
165 scoped_ptr<GpuScheduler> gpu_scheduler_; | 164 scoped_ptr<GpuScheduler> gpu_scheduler_; |
166 CommandParser* parser_; | |
167 scoped_ptr<CommandBufferHelper> helper_; | 165 scoped_ptr<CommandBufferHelper> helper_; |
168 Sequence sequence_; | 166 Sequence sequence_; |
169 scoped_ptr<DoJumpCommand> do_jump_command_; | 167 scoped_ptr<DoJumpCommand> do_jump_command_; |
170 }; | 168 }; |
171 | 169 |
172 // Checks that commands in the buffer are properly executed, and that the | 170 // Checks that commands in the buffer are properly executed, and that the |
173 // status/error stay valid. | 171 // status/error stay valid. |
174 TEST_F(CommandBufferHelperTest, TestCommandProcessing) { | 172 TEST_F(CommandBufferHelperTest, TestCommandProcessing) { |
175 // Check initial state of the engine - it should have been configured by the | 173 // Check initial state of the engine - it should have been configured by the |
176 // helper. | 174 // helper. |
177 EXPECT_TRUE(parser_ != NULL); | 175 EXPECT_TRUE(GetParser() != NULL); |
178 EXPECT_EQ(error::kNoError, GetError()); | 176 EXPECT_EQ(error::kNoError, GetError()); |
179 EXPECT_EQ(0, GetGetOffset()); | 177 EXPECT_EQ(0, GetGetOffset()); |
180 | 178 |
181 // Add 3 commands through the helper | 179 // Add 3 commands through the helper |
182 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL); | 180 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL); |
183 | 181 |
184 CommandBufferEntry args1[2]; | 182 CommandBufferEntry args1[2]; |
185 args1[0].value_uint32 = 3; | 183 args1[0].value_uint32 = 3; |
186 args1[1].value_float = 4.f; | 184 args1[1].value_float = 4.f; |
187 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args1); | 185 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args1); |
188 | 186 |
189 CommandBufferEntry args2[2]; | 187 CommandBufferEntry args2[2]; |
190 args2[0].value_uint32 = 5; | 188 args2[0].value_uint32 = 5; |
191 args2[1].value_float = 6.f; | 189 args2[1].value_float = 6.f; |
192 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args2); | 190 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args2); |
193 | 191 |
194 // Wait until it's done. | 192 // Wait until it's done. |
195 helper_->Finish(); | 193 helper_->Finish(); |
196 // Check that the engine has no more work to do. | 194 // Check that the engine has no more work to do. |
197 EXPECT_TRUE(parser_->IsEmpty()); | 195 EXPECT_TRUE(GetParser()->IsEmpty()); |
198 | 196 |
199 // Check that the commands did happen. | 197 // Check that the commands did happen. |
200 Mock::VerifyAndClearExpectations(api_mock_.get()); | 198 Mock::VerifyAndClearExpectations(api_mock_.get()); |
201 | 199 |
202 // Check the error status. | 200 // Check the error status. |
203 EXPECT_EQ(error::kNoError, GetError()); | 201 EXPECT_EQ(error::kNoError, GetError()); |
204 } | 202 } |
205 | 203 |
206 // Checks that commands in the buffer are properly executed when wrapping the | 204 // Checks that commands in the buffer are properly executed when wrapping the |
207 // buffer, and that the status/error stay valid. | 205 // buffer, and that the status/error stay valid. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 EXPECT_LE(command1_put, GetGetOffset()); | 300 EXPECT_LE(command1_put, GetGetOffset()); |
303 helper_->Finish(); | 301 helper_->Finish(); |
304 | 302 |
305 // Check that the commands did happen. | 303 // Check that the commands did happen. |
306 Mock::VerifyAndClearExpectations(api_mock_.get()); | 304 Mock::VerifyAndClearExpectations(api_mock_.get()); |
307 | 305 |
308 // Check the error status. | 306 // Check the error status. |
309 EXPECT_EQ(error::kNoError, GetError()); | 307 EXPECT_EQ(error::kNoError, GetError()); |
310 } | 308 } |
311 | 309 |
| 310 TEST_F(CommandBufferHelperTest, FreeRingBuffer) { |
| 311 EXPECT_TRUE(helper_->HaveRingBuffer()); |
| 312 |
| 313 // Test freeing ring buffer. |
| 314 helper_->FreeRingBuffer(); |
| 315 EXPECT_FALSE(helper_->HaveRingBuffer()); |
| 316 |
| 317 // Test that InsertToken allocates a new one |
| 318 int32 token = helper_->InsertToken(); |
| 319 EXPECT_TRUE(helper_->HaveRingBuffer()); |
| 320 EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _)) |
| 321 .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken), |
| 322 Return(error::kNoError))); |
| 323 helper_->WaitForToken(token); |
| 324 helper_->FreeRingBuffer(); |
| 325 EXPECT_FALSE(helper_->HaveRingBuffer()); |
| 326 |
| 327 // Test that WaitForAvailableEntries allocates a new one |
| 328 AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL); |
| 329 EXPECT_TRUE(helper_->HaveRingBuffer()); |
| 330 helper_->Finish(); |
| 331 helper_->FreeRingBuffer(); |
| 332 EXPECT_FALSE(helper_->HaveRingBuffer()); |
| 333 |
| 334 // Check that the commands did happen. |
| 335 Mock::VerifyAndClearExpectations(api_mock_.get()); |
| 336 } |
| 337 |
312 } // namespace gpu | 338 } // namespace gpu |
OLD | NEW |