blob: ce912109cf9540c9666f3f5926360e3809b3506c [file] [log] [blame]
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/message_loop.h"
#include "gpu/command_buffer/common/command_buffer_mock.h"
#include "gpu/command_buffer/service/gpu_processor.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
#include "gpu/command_buffer/service/mocks.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gmock/include/gmock/gmock.h"
using testing::_;
using testing::DoAll;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;
using testing::SetArgumentPointee;
using testing::StrictMock;
namespace gpu {
const size_t kRingBufferSize = 1024;
const size_t kRingBufferEntries = kRingBufferSize / sizeof(CommandBufferEntry);
class GPUProcessorTest : public testing::Test {
protected:
virtual void SetUp() {
shared_memory_.reset(new ::base::SharedMemory);
shared_memory_->CreateAndMapAnonymous(kRingBufferSize);
buffer_ = static_cast<int32*>(shared_memory_->memory());
shared_memory_buffer_.ptr = buffer_;
shared_memory_buffer_.size = kRingBufferSize;
memset(buffer_, 0, kRingBufferSize);
command_buffer_.reset(new MockCommandBuffer);
ON_CALL(*command_buffer_.get(), GetRingBuffer())
.WillByDefault(Return(shared_memory_buffer_));
CommandBuffer::State default_state;
default_state.num_entries = kRingBufferEntries;
ON_CALL(*command_buffer_.get(), GetState())
.WillByDefault(Return(default_state));
async_api_.reset(new StrictMock<AsyncAPIMock>);
decoder_ = new gles2::MockGLES2Decoder();
parser_ = new CommandParser(buffer_,
kRingBufferEntries,
0,
kRingBufferEntries,
0,
async_api_.get());
processor_.reset(new GPUProcessor(command_buffer_.get(),
decoder_,
parser_,
2));
EXPECT_CALL(*decoder_, Destroy())
.Times(1)
.RetiresOnSaturation();
}
virtual void TearDown() {
// Ensure that any unexpected tasks posted by the GPU processor are executed
// in order to fail the test.
MessageLoop::current()->RunAllPending();
}
error::Error GetError() {
return command_buffer_->GetState().error;
}
base::mac::ScopedNSAutoreleasePool autorelease_pool_;
MessageLoop message_loop;
scoped_ptr<MockCommandBuffer> command_buffer_;
scoped_ptr<base::SharedMemory> shared_memory_;
Buffer shared_memory_buffer_;
int32* buffer_;
gles2::MockGLES2Decoder* decoder_;
CommandParser* parser_;
scoped_ptr<AsyncAPIMock> async_api_;
scoped_ptr<GPUProcessor> processor_;
};
TEST_F(GPUProcessorTest, ProcessorDoesNothingIfRingBufferIsEmpty) {
CommandBuffer::State state;
state.put_offset = 0;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*command_buffer_, SetGetOffset(0));
EXPECT_CALL(*command_buffer_, SetParseError(_))
.Times(0);
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, ProcessesOneCommand) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 2;
buffer_[1] = 123;
CommandBuffer::State state;
state.put_offset = 2;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*command_buffer_, SetGetOffset(2));
EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*command_buffer_, SetParseError(_))
.Times(0);
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, ProcessesTwoCommands) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 2;
buffer_[1] = 123;
header[2].command = 8;
header[2].size = 1;
CommandBuffer::State state;
state.put_offset = 3;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*command_buffer_, SetGetOffset(3));
EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
.WillOnce(Return(error::kNoError));
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, ProcessorSetsTheGLContext) {
EXPECT_CALL(*decoder_, MakeCurrent())
.WillOnce(Return(true))
.WillOnce(Return(true));
CommandBuffer::State state;
state.put_offset = 0;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*command_buffer_, SetGetOffset(0));
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, PostsTaskToFinishRemainingCommands) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 2;
buffer_[1] = 123;
header[2].command = 8;
header[2].size = 1;
header[3].command = 9;
header[3].size = 1;
CommandBuffer::State state;
state.put_offset = 4;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*async_api_, DoCommand(7, 1, &buffer_[0]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*async_api_, DoCommand(8, 0, &buffer_[2]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*command_buffer_, SetGetOffset(3));
processor_->ProcessCommands();
// ProcessCommands is called a second time when the pending task is run.
state.put_offset = 4;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*async_api_, DoCommand(9, 0, &buffer_[3]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*command_buffer_, SetGetOffset(4));
MessageLoop::current()->RunAllPending();
}
TEST_F(GPUProcessorTest, SetsErrorCodeOnCommandBuffer) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 1;
CommandBuffer::State state;
state.put_offset = 1;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
EXPECT_CALL(*async_api_, DoCommand(7, 0, &buffer_[0]))
.WillOnce(Return(
error::kUnknownCommand));
EXPECT_CALL(*command_buffer_,
SetParseError(error::kUnknownCommand));
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, ProcessCommandsDoesNothingAfterError) {
CommandBuffer::State state;
state.error = error::kGenericError;
EXPECT_CALL(*command_buffer_, GetState())
.WillOnce(Return(state));
processor_->ProcessCommands();
}
TEST_F(GPUProcessorTest, CanGetAddressOfSharedMemory) {
EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_EQ(&buffer_[0], processor_->GetSharedMemoryBuffer(7).ptr);
}
ACTION_P2(SetPointee, address, value) {
*address = value;
}
TEST_F(GPUProcessorTest, CanGetSizeOfSharedMemory) {
EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_EQ(kRingBufferSize, processor_->GetSharedMemoryBuffer(7).size);
}
TEST_F(GPUProcessorTest, SetTokenForwardsToCommandBuffer) {
EXPECT_CALL(*command_buffer_, SetToken(7));
processor_->set_token(7);
}
} // namespace gpu