| 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 |