9#include "flutter/impeller/golden_tests/golden_playground_test.h"
11#include "flutter/impeller/aiks/picture.h"
12#include "flutter/impeller/golden_tests/golden_digest.h"
13#include "flutter/impeller/golden_tests/metal_screenshotter.h"
14#include "flutter/impeller/golden_tests/vulkan_screenshotter.h"
15#include "flutter/third_party/abseil-cpp/absl/base/no_destructor.h"
22#define GLFW_INCLUDE_NONE
23#include "third_party/glfw/include/GLFW/glfw3.h"
28std::unique_ptr<PlaygroundImpl> MakeVulkanPlayground(
bool enable_validations) {
30 PlaygroundSwitches playground_switches;
31 playground_switches.enable_vulkan_validation = enable_validations;
37const std::unique_ptr<PlaygroundImpl>& GetSharedVulkanPlayground(
38 bool enable_validations) {
39 if (enable_validations) {
40 static absl::NoDestructor<std::unique_ptr<PlaygroundImpl>>
41 vulkan_validation_playground(
42 MakeVulkanPlayground(
true));
46 [&] { (*vulkan_validation_playground)->GetContext()->
Shutdown(); });
47 return *vulkan_validation_playground;
49 static absl::NoDestructor<std::unique_ptr<PlaygroundImpl>>
50 vulkan_playground(MakeVulkanPlayground(
false));
54 [&] { (*vulkan_playground)->GetContext()->
Shutdown(); });
55 return *vulkan_playground;
60#define IMP_AIKSTEST(name) \
61 "impeller_Play_AiksTest_" #name "_Metal", \
62 "impeller_Play_AiksTest_" #name "_OpenGLES", \
63 "impeller_Play_AiksTest_" #name "_Vulkan"
72 "impeller_Play_AiksTest_CanRenderClippedRuntimeEffects_Vulkan",
76std::string GetTestName() {
77 std::string suite_name =
78 ::testing::UnitTest::GetInstance()->current_test_suite()->name();
79 std::string test_name =
80 ::testing::UnitTest::GetInstance()->current_test_info()->name();
82 ss <<
"impeller_" << suite_name <<
"_" << test_name;
83 std::string
result = ss.str();
89std::string GetGoldenFilename() {
90 return GetTestName() +
".png";
93bool SaveScreenshot(std::unique_ptr<testing::Screenshot> screenshot) {
94 if (!screenshot || !screenshot->GetBytes()) {
95 FML_LOG(
ERROR) <<
"Failed to collect screenshot for test " << GetTestName();
98 std::string test_name = GetTestName();
99 std::string filename = GetGoldenFilename();
101 test_name, filename, screenshot->GetWidth(), screenshot->GetHeight());
102 if (!screenshot->WriteToPNG(
104 FML_LOG(
ERROR) <<
"Failed to write screenshot to " << filename;
126 std::shared_ptr<TypographerContext> typographer_context) {
127 typographer_context_ = std::move(typographer_context);
131 ASSERT_FALSE(dlopen(
"/usr/local/lib/libMoltenVK.dylib", RTLD_NOLOAD));
135bool DoesSupportWideGamutTests() {
152 setenv(
"VK_ICD_FILENAMES", icd_path.c_str(), 1);
154 std::string test_name = GetTestName();
155 bool enable_wide_gamut = test_name.find(
"WideGamut_") != std::string::npos;
156 switch (GetParam()) {
158 if (!DoesSupportWideGamutTests()) {
160 "This metal device doesn't support wide gamut golden tests.");
162 pimpl_->screenshotter =
163 std::make_unique<testing::MetalScreenshotter>(enable_wide_gamut);
166 if (enable_wide_gamut) {
167 GTEST_SKIP_(
"Vulkan doesn't support wide gamut golden tests.");
169 const std::unique_ptr<PlaygroundImpl>& playground =
170 GetSharedVulkanPlayground(
true);
171 pimpl_->screenshotter =
172 std::make_unique<testing::VulkanScreenshotter>(playground);
176 if (enable_wide_gamut) {
177 GTEST_SKIP_(
"OpenGLES doesn't support wide gamut golden tests.");
184 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
185 pimpl_->test_opengl_playground);
193 "GoldenPlaygroundTest doesn't support interactive playground tests "
198 "gpu_string",
GetContext()->DescribeGpuModel());
208 auto screenshot = pimpl_->screenshotter->MakeScreenshot(
renderer,
picture,
209 pimpl_->window_size);
210 return SaveScreenshot(std::move(screenshot));
217 std::optional<Picture>
picture;
218 std::unique_ptr<testing::Screenshot> screenshot;
219 for (
int i = 0;
i < 2; ++
i) {
222 display_list->Dispatch(dispatcher);
226 pimpl_->window_size);
229 return SaveScreenshot(std::move(screenshot));
237 std::optional<Picture>
picture;
238 std::unique_ptr<testing::Screenshot> screenshot;
239 for (
int i = 0;
i < 2; ++
i) {
244 screenshot = pimpl_->screenshotter->MakeScreenshot(
248 return SaveScreenshot(std::move(screenshot));
261 ImGuiWindowFlags
flags) {
266 const char* fixture_name,
267 bool enable_mipmapping)
const {
268 std::shared_ptr<fml::Mapping> mapping =
273 result->SetLabel(fixture_name);
279 const char* fixture_name,
280 bool enable_mipmapping)
const {
281 std::shared_ptr<Texture>
texture =
287 const char* asset_name)
const {
288 const std::shared_ptr<fml::Mapping> fixture =
290 if (!fixture || fixture->GetSize() == 0) {
297 return pimpl_->screenshotter->GetPlayground().GetContext();
305 bool enable_vulkan_validations =
true;
306 FML_CHECK(!pimpl_->test_vulkan_playground)
307 <<
"We don't support creating multiple contexts for one test";
308 pimpl_->test_vulkan_playground =
309 MakeVulkanPlayground(enable_vulkan_validations);
310 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
311 pimpl_->test_vulkan_playground);
312 return pimpl_->test_vulkan_playground->GetContext();
320 return pimpl_->screenshotter->GetPlayground().GetContentScale();
328 return pimpl_->window_size;
331void GoldenPlaygroundTest::GoldenPlaygroundTest::SetWindowSize(
ISize size) {
332 pimpl_->window_size =
size;
336 const std::shared_ptr<Capabilities>& capabilities) {
337 return pimpl_->screenshotter->GetPlayground().SetCapabilities(capabilities);
int find(T *array, int N, T item)
void Dispatch(DlOpReceiver &ctx) const
Wraps a closure that is invoked in the destructor unless released by the caller.
Picture EndRecordingAsPicture()
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
PlaygroundBackend GetBackend() const
ISize GetWindowSize() const
std::function< std::optional< Picture >(AiksContext &renderer)> AiksPlaygroundCallback
sk_sp< flutter::DlImage > CreateDlImageForFixture(const char *fixture_name, bool enable_mipmapping=false) const
Point GetContentScale() const
fml::Status SetCapabilities(const std::shared_ptr< Capabilities > &capabilities)
void SetTypographerContext(std::shared_ptr< TypographerContext > typographer_context)
std::shared_ptr< Context > MakeContext() const
Scalar GetSecondsElapsed() const
RuntimeStage::Map OpenAssetAsRuntimeStage(const char *asset_name) const
bool OpenPlaygroundHere(Picture picture)
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
std::function< sk_sp< flutter::DisplayList >()> AiksDlPlaygroundCallback
~GoldenPlaygroundTest() override
std::shared_ptr< Context > GetContext() const
std::shared_ptr< Texture > CreateTextureForFixture(const char *fixture_name, bool enable_mipmapping=false) const
static std::unique_ptr< PlaygroundImpl > Create(PlaygroundBackend backend, PlaygroundSwitches switches)
static std::shared_ptr< Texture > CreateTextureForMapping(const std::shared_ptr< Context > &context, std::shared_ptr< fml::Mapping > mapping, bool enable_mipmapping=false)
std::map< RuntimeStageBackend, std::shared_ptr< RuntimeStage > > Map
static Map DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
static GoldenDigest * Instance()
void AddDimension(const std::string &name, const std::string &value)
void AddImage(const std::string &test_name, const std::string &filename, int32_t width, int32_t height)
std::string GetFilenamePath(const std::string &filename) const
static WorkingDirectory * Instance()
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define IMP_AIKSTEST(name)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
sk_sp< const SkPicture > picture
static void Shutdown(Dart_NativeArguments args)
const char * GetTestingAssetsPath()
Returns the directory containing assets shared across all tests.
std::unique_ptr< fml::Mapping > OpenFixtureAsMapping(const std::string &fixture_name)
Opens a fixture of the given file name and returns a mapping to its contents.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static const std::vector< std::string > kSkipTests
std::unique_ptr< PlaygroundImpl > test_vulkan_playground
std::unique_ptr< testing::Screenshotter > screenshotter
std::unique_ptr< PlaygroundImpl > test_opengl_playground