blob: c17703ad3d33bb6d4e73a7a7dad8e4168b0639dc [file] [log] [blame]
// Copyright (c) 2011 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 "gpu/command_buffer/service/command_executor.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/run_loop.h"
#include "gpu/command_buffer/common/command_buffer_mock.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/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.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;
class CommandExecutorTest : public testing::Test {
protected:
static const int32_t kTransferBufferId = 123;
void SetUp() override {
std::unique_ptr<base::SharedMemory> shared_memory(new ::base::SharedMemory);
shared_memory->CreateAndMapAnonymous(kRingBufferSize);
buffer_ = static_cast<int32_t*>(shared_memory->memory());
shared_memory_buffer_ =
MakeBufferFromSharedMemory(std::move(shared_memory), kRingBufferSize);
memset(buffer_, 0, kRingBufferSize);
command_buffer_.reset(new MockCommandBuffer);
CommandBuffer::State default_state;
ON_CALL(*command_buffer_.get(), GetLastState())
.WillByDefault(Return(default_state));
ON_CALL(*command_buffer_.get(), GetPutOffset()).WillByDefault(Return(0));
decoder_.reset(new gles2::MockGLES2Decoder());
// Install FakeDoCommands handler so we can use individual DoCommand()
// expectations.
EXPECT_CALL(*decoder_, DoCommands(_, _, _, _))
.WillRepeatedly(
Invoke(decoder_.get(), &gles2::MockGLES2Decoder::FakeDoCommands));
executor_.reset(new gpu::CommandExecutor(command_buffer_.get(),
decoder_.get(), decoder_.get()));
EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_CALL(*command_buffer_, SetGetOffset(0));
EXPECT_TRUE(executor_->SetGetBuffer(kTransferBufferId));
}
void TearDown() override {
// Ensure that any unexpected tasks posted by the GPU scheduler are executed
// in order to fail the test.
base::RunLoop().RunUntilIdle();
}
error::Error GetError() { return command_buffer_->GetLastState().error; }
std::unique_ptr<MockCommandBuffer> command_buffer_;
scoped_refptr<Buffer> shared_memory_buffer_;
int32_t* buffer_;
std::unique_ptr<gles2::MockGLES2Decoder> decoder_;
std::unique_ptr<CommandExecutor> executor_;
base::MessageLoop message_loop_;
};
TEST_F(CommandExecutorTest, ExecutorDoesNothingIfRingBufferIsEmpty) {
CommandBuffer::State state;
EXPECT_CALL(*command_buffer_, GetLastState()).WillRepeatedly(Return(state));
EXPECT_CALL(*command_buffer_, SetParseError(_)).Times(0);
executor_->PutChanged();
}
TEST_F(CommandExecutorTest, GetSetBuffer) {
CommandBuffer::State state;
// Set the get offset to something not 0.
EXPECT_CALL(*command_buffer_, SetGetOffset(2));
executor_->SetGetOffset(2);
EXPECT_EQ(2, executor_->GetGetOffset());
// Set the buffer.
EXPECT_CALL(*command_buffer_, GetTransferBuffer(kTransferBufferId))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_CALL(*command_buffer_, SetGetOffset(0));
EXPECT_TRUE(executor_->SetGetBuffer(kTransferBufferId));
// Check the get offset was reset.
EXPECT_EQ(0, executor_->GetGetOffset());
}
TEST_F(CommandExecutorTest, ProcessesOneCommand) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 2;
buffer_[1] = 123;
CommandBuffer::State state;
EXPECT_CALL(*command_buffer_, GetLastState()).WillRepeatedly(Return(state));
EXPECT_CALL(*command_buffer_, GetPutOffset()).WillRepeatedly(Return(2));
EXPECT_CALL(*command_buffer_, SetGetOffset(2));
EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*command_buffer_, SetParseError(_)).Times(0);
executor_->PutChanged();
}
TEST_F(CommandExecutorTest, 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;
EXPECT_CALL(*command_buffer_, GetLastState()).WillRepeatedly(Return(state));
EXPECT_CALL(*command_buffer_, GetPutOffset()).WillRepeatedly(Return(3));
EXPECT_CALL(*decoder_, DoCommand(7, 1, &buffer_[0]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*decoder_, DoCommand(8, 0, &buffer_[2]))
.WillOnce(Return(error::kNoError));
EXPECT_CALL(*command_buffer_, SetGetOffset(3));
executor_->PutChanged();
}
TEST_F(CommandExecutorTest, SetsErrorCodeOnCommandBuffer) {
CommandHeader* header = reinterpret_cast<CommandHeader*>(&buffer_[0]);
header[0].command = 7;
header[0].size = 1;
CommandBuffer::State state;
EXPECT_CALL(*command_buffer_, GetLastState()).WillRepeatedly(Return(state));
EXPECT_CALL(*command_buffer_, GetPutOffset()).WillRepeatedly(Return(1));
EXPECT_CALL(*decoder_, DoCommand(7, 0, &buffer_[0]))
.WillOnce(Return(error::kUnknownCommand));
EXPECT_CALL(*command_buffer_, SetGetOffset(1));
EXPECT_CALL(*command_buffer_, SetContextLostReason(_));
EXPECT_CALL(*decoder_, GetContextLostReason())
.WillOnce(Return(error::kUnknown));
EXPECT_CALL(*command_buffer_, SetParseError(error::kUnknownCommand));
executor_->PutChanged();
}
TEST_F(CommandExecutorTest, ProcessCommandsDoesNothingAfterError) {
CommandBuffer::State state;
state.error = error::kGenericError;
EXPECT_CALL(*command_buffer_, GetLastState()).WillRepeatedly(Return(state));
executor_->PutChanged();
}
TEST_F(CommandExecutorTest, CanGetAddressOfSharedMemory) {
EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_EQ(&buffer_[0], executor_->GetSharedMemoryBuffer(7)->memory());
}
ACTION_P2(SetPointee, address, value) {
*address = value;
}
TEST_F(CommandExecutorTest, CanGetSizeOfSharedMemory) {
EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
.WillOnce(Return(shared_memory_buffer_));
EXPECT_EQ(kRingBufferSize, executor_->GetSharedMemoryBuffer(7)->size());
}
TEST_F(CommandExecutorTest, SetTokenForwardsToCommandBuffer) {
EXPECT_CALL(*command_buffer_, SetToken(7));
executor_->set_token(7);
}
} // namespace gpu