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
3 // found in the LICENSE file.
5 #include "base/message_loop/message_loop.h"
6 #include "gpu/command_buffer/common/command_buffer_mock.h"
7 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
8 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
9 #include "gpu/command_buffer/service/gpu_scheduler.h"
10 #include "gpu/command_buffer/service/mocks.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 #if defined(OS_MACOSX)
15 #include "base/mac/scoped_nsautorelease_pool.h"
20 using testing::Invoke;
21 using testing::NiceMock;
22 using testing::Return;
23 using testing::SetArgumentPointee;
24 using testing::StrictMock;
28 const size_t kRingBufferSize = 1024;
29 const size_t kRingBufferEntries = kRingBufferSize / sizeof(CommandBufferEntry);
31 class GpuSchedulerTest : public testing::Test {
33 static const int32 kTransferBufferId = 123;
35 virtual void SetUp() {
36 shared_memory_.reset(new ::base::SharedMemory);
37 shared_memory_->CreateAndMapAnonymous(kRingBufferSize);
38 buffer_ = static_cast<int32*>(shared_memory_->memory());
39 shared_memory_buffer_.ptr = buffer_;
40 shared_memory_buffer_.size = kRingBufferSize;
41 memset(buffer_, 0, kRingBufferSize);
43 command_buffer_.reset(new MockCommandBuffer);
45 CommandBuffer::State default_state;
46 default_state.num_entries = kRingBufferEntries;
47 ON_CALL(*command_buffer_.get(), GetState())
48 .WillByDefault(Return(default_state));
50 decoder_.reset(new gles2::MockGLES2Decoder());
51 scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
54 EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId))
55 .WillOnce(Return(shared_memory_buffer_));
56 EXPECT_CALL(*command_buffer_, SetGetOffset(0));
57 EXPECT_TRUE(scheduler_->SetGetBuffer(kTransferBufferId));
60 virtual void TearDown() {
61 // Ensure that any unexpected tasks posted by the GPU scheduler are executed
62 // in order to fail the test.
63 base::MessageLoop::current()->RunUntilIdle();
66 error::Error GetError() {
67 return command_buffer_->GetState().error;
70 #if defined(OS_MACOSX)
71 base::mac::ScopedNSAutoreleasePool autorelease_pool_;
73 base::MessageLoop message_loop;
74 scoped_ptr<MockCommandBuffer> command_buffer_;
75 scoped_ptr<base::SharedMemory> shared_memory_;
76 Buffer shared_memory_buffer_;
78 scoped_ptr<gles2::MockGLES2Decoder> decoder_;
79 scoped_ptr<GpuScheduler> scheduler_;
82 TEST_F(GpuSchedulerTest, SchedulerDoesNothingIfRingBufferIsEmpty) {
83 CommandBuffer::State state;
86 EXPECT_CALL(*command_buffer_, GetState())
87 .WillRepeatedly(Return(state));
89 EXPECT_CALL(*command_buffer_, SetParseError(_))
92 scheduler_->PutChanged();
95 TEST_F(GpuSchedulerTest, GetSetBuffer) {
96 CommandBuffer::State state;
98 // Set the get offset to something not 0.
99 EXPECT_CALL(*command_buffer_, SetGetOffset(2));
100 scheduler_->SetGetOffset(2);
101 EXPECT_EQ(2, scheduler_->GetGetOffset());
104 EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId))
105 .WillOnce(Return(shared_memory_buffer_));
106 EXPECT_CALL(*command_buffer_, SetGetOffset(0));
107 EXPECT_TRUE(scheduler_->SetGetBuffer(kTransferBufferId));
109 // Check the get offset was reset.
110 EXPECT_EQ(0, scheduler_->GetGetOffset());
113 TEST_F(GpuSchedulerTest, ProcessesOneCommand) {
114 CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
115 header[0].command = 7;
119 CommandBuffer::State state;
121 state.put_offset = 2;
122 EXPECT_CALL(*command_buffer_, GetState())
123 .WillRepeatedly(Return(state));
124 EXPECT_CALL(*command_buffer_, SetGetOffset(2));
126 EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0]))
127 .WillOnce(Return(error::kNoError));
129 EXPECT_CALL(*command_buffer_, SetParseError(_))
132 scheduler_->PutChanged();
135 TEST_F(GpuSchedulerTest, ProcessesTwoCommands) {
136 CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
137 header[0].command = 7;
140 header[2].command = 8;
143 CommandBuffer::State state;
145 state.put_offset = 3;
146 EXPECT_CALL(*command_buffer_, GetState())
147 .WillRepeatedly(Return(state));
149 EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0]))
150 .WillOnce(Return(error::kNoError));
151 EXPECT_CALL(*command_buffer_, SetGetOffset(2));
153 EXPECT_CALL(*decoder_, DoCommand(8, 0, &buffer_[2]))
154 .WillOnce(Return(error::kNoError));
155 EXPECT_CALL(*command_buffer_, SetGetOffset(3));
157 scheduler_->PutChanged();
160 TEST_F(GpuSchedulerTest, SetsErrorCodeOnCommandBuffer) {
161 CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
162 header[0].command = 7;
165 CommandBuffer::State state;
167 state.put_offset = 1;
168 EXPECT_CALL(*command_buffer_, GetState())
169 .WillRepeatedly(Return(state));
171 EXPECT_CALL(*decoder_, DoCommand(7, 0, &buffer_[0]))
173 error::kUnknownCommand));
174 EXPECT_CALL(*command_buffer_, SetGetOffset(1));
176 EXPECT_CALL(*command_buffer_, SetContextLostReason(_));
177 EXPECT_CALL(*decoder_, GetContextLostReason())
178 .WillOnce(Return(error::kUnknown));
179 EXPECT_CALL(*command_buffer_,
180 SetParseError(error::kUnknownCommand));
182 scheduler_->PutChanged();
185 TEST_F(GpuSchedulerTest, ProcessCommandsDoesNothingAfterError) {
186 CommandBuffer::State state;
187 state.error = error::kGenericError;
189 EXPECT_CALL(*command_buffer_, GetState())
190 .WillRepeatedly(Return(state));
192 scheduler_->PutChanged();
195 TEST_F(GpuSchedulerTest, CanGetAddressOfSharedMemory) {
196 EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
197 .WillOnce(Return(shared_memory_buffer_));
199 EXPECT_EQ(&buffer_[0], scheduler_->GetSharedMemoryBuffer(7).ptr);
202 ACTION_P2(SetPointee, address, value) {
206 TEST_F(GpuSchedulerTest, CanGetSizeOfSharedMemory) {
207 EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
208 .WillOnce(Return(shared_memory_buffer_));
210 EXPECT_EQ(kRingBufferSize, scheduler_->GetSharedMemoryBuffer(7).size);
213 TEST_F(GpuSchedulerTest, SetTokenForwardsToCommandBuffer) {
214 EXPECT_CALL(*command_buffer_, SetToken(7));
215 scheduler_->set_token(7);