blob: dd1882f7d17aec4508ceba46c09644f0950093dc [file]
// Copyright 2013 The Flutter 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 "flutter/lib/gpu/command_buffer.h"
#include <memory>
#include <vector>
#include "fml/status.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "impeller/renderer/testing/mocks.h"
namespace flutter::gpu {
namespace {
using ::impeller::testing::MockCommandBuffer;
using ::impeller::testing::MockCommandQueue;
using ::impeller::testing::MockImpellerContext;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
TEST(FlutterGpuCommandBufferTest,
InvokesRegisteredCompletionCallbacksOnSubmit) {
auto context = std::make_shared<MockImpellerContext>();
auto impeller_command_buffer = std::make_shared<MockCommandBuffer>(context);
auto command_queue = std::make_shared<MockCommandQueue>();
CommandBuffer command_buffer(context, impeller_command_buffer);
std::vector<impeller::CommandBuffer::Status> statuses;
EXPECT_TRUE(command_buffer.AddCompletionCallback(
[&statuses](impeller::CommandBuffer::Status status) {
statuses.push_back(status);
}));
EXPECT_TRUE(command_buffer.AddCompletionCallback(
[&statuses](impeller::CommandBuffer::Status status) {
statuses.push_back(status);
}));
EXPECT_CALL(*context, GetBackendType)
.WillOnce(Return(impeller::Context::BackendType::kMetal));
EXPECT_CALL(*context, GetCommandQueue).WillOnce(Return(command_queue));
EXPECT_CALL(*command_queue, Submit(_, _, _))
.WillOnce(DoAll(
[](const std::vector<std::shared_ptr<impeller::CommandBuffer>>&
buffers,
const impeller::CommandQueue::CompletionCallback& callback,
bool block_on_schedule) {
EXPECT_EQ(buffers.size(), 1u);
EXPECT_FALSE(block_on_schedule);
callback(impeller::CommandBuffer::Status::kCompleted);
},
Return(fml::Status())));
EXPECT_TRUE(command_buffer.Submit(
[&statuses](impeller::CommandBuffer::Status status) {
statuses.push_back(status);
}));
EXPECT_EQ(statuses.size(), 3u);
EXPECT_EQ(statuses[0], impeller::CommandBuffer::Status::kCompleted);
EXPECT_EQ(statuses[1], impeller::CommandBuffer::Status::kCompleted);
EXPECT_EQ(statuses[2], impeller::CommandBuffer::Status::kCompleted);
}
TEST(FlutterGpuCommandBufferTest, RejectsCompletionCallbacksAfterSubmit) {
auto context = std::make_shared<MockImpellerContext>();
auto impeller_command_buffer = std::make_shared<MockCommandBuffer>(context);
auto command_queue = std::make_shared<MockCommandQueue>();
CommandBuffer command_buffer(context, impeller_command_buffer);
EXPECT_CALL(*context, GetBackendType)
.WillOnce(Return(impeller::Context::BackendType::kMetal));
EXPECT_CALL(*context, GetCommandQueue).WillOnce(Return(command_queue));
EXPECT_CALL(*command_queue, Submit(_, _, _)).WillOnce(Return(fml::Status()));
EXPECT_TRUE(command_buffer.Submit());
EXPECT_FALSE(command_buffer.AddCompletionCallback(
[](impeller::CommandBuffer::Status status) { (void)status; }));
EXPECT_FALSE(command_buffer.Submit());
}
TEST(FlutterGpuCommandBufferTest,
InvokesRegisteredCompletionCallbacksWhenSubmitFails) {
auto context = std::make_shared<MockImpellerContext>();
auto impeller_command_buffer = std::make_shared<MockCommandBuffer>(context);
auto command_queue = std::make_shared<MockCommandQueue>();
CommandBuffer command_buffer(context, impeller_command_buffer);
std::vector<impeller::CommandBuffer::Status> statuses;
EXPECT_TRUE(command_buffer.AddCompletionCallback(
[&statuses](impeller::CommandBuffer::Status status) {
statuses.push_back(status);
}));
EXPECT_CALL(*context, GetBackendType)
.WillOnce(Return(impeller::Context::BackendType::kMetal));
EXPECT_CALL(*context, GetCommandQueue).WillOnce(Return(command_queue));
EXPECT_CALL(*command_queue, Submit(_, _, _))
.WillOnce(Return(fml::Status(fml::StatusCode::kInternal,
"Command queue submit failed.")));
EXPECT_FALSE(command_buffer.Submit());
EXPECT_EQ(statuses.size(), 1u);
EXPECT_EQ(statuses[0], impeller::CommandBuffer::Status::kError);
}
} // namespace
} // namespace flutter::gpu