Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Variables
golden_playground_test_mac.cc File Reference
#include <dlfcn.h>
#include <filesystem>
#include <memory>
#include "flutter/impeller/golden_tests/golden_playground_test.h"
#include "flutter/impeller/aiks/picture.h"
#include "flutter/impeller/golden_tests/golden_digest.h"
#include "flutter/impeller/golden_tests/metal_screenshotter.h"
#include "flutter/impeller/golden_tests/vulkan_screenshotter.h"
#include "flutter/third_party/abseil-cpp/absl/base/no_destructor.h"
#include "impeller/typographer/backends/skia/typographer_context_skia.h"
#include "impeller/typographer/typographer_context.h"
#include "third_party/glfw/include/GLFW/glfw3.h"

Go to the source code of this file.

Classes

struct  impeller::GoldenPlaygroundTest::GoldenPlaygroundTestImpl
 

Namespaces

namespace  impeller
 

Macros

#define GLFW_INCLUDE_NONE
 
#define IMP_AIKSTEST(name)
 

Variables

static const std::vector< std::string > impeller::kSkipTests
 

Macro Definition Documentation

◆ GLFW_INCLUDE_NONE

#define GLFW_INCLUDE_NONE

Definition at line 19 of file golden_playground_test_mac.cc.

◆ IMP_AIKSTEST

#define IMP_AIKSTEST (   name)
Value:
"impeller_Play_AiksTest_" #name "_Metal", \
"impeller_Play_AiksTest_" #name "_OpenGLES", \
"impeller_Play_AiksTest_" #name "_Vulkan"
const char * name
Definition fuchsia.cc:50

Definition at line 57 of file golden_playground_test_mac.cc.

63 {
64 // TextRotated is flakey and we can't seem to get it to stabilize on Skia
65 // Gold.
66 IMP_AIKSTEST(TextRotated),
67 // Runtime stage based tests get confused with a Metal context.
68 "impeller_Play_AiksTest_CanRenderClippedRuntimeEffects_Vulkan",
69};
70
71namespace {
72std::string GetTestName() {
73 std::string suite_name =
74 ::testing::UnitTest::GetInstance()->current_test_suite()->name();
75 std::string test_name =
76 ::testing::UnitTest::GetInstance()->current_test_info()->name();
77 std::stringstream ss;
78 ss << "impeller_" << suite_name << "_" << test_name;
79 std::string result = ss.str();
80 // Make sure there are no slashes in the test name.
81 std::replace(result.begin(), result.end(), '/', '_');
82 return result;
83}
84
85std::string GetGoldenFilename() {
86 return GetTestName() + ".png";
87}
88
89bool SaveScreenshot(std::unique_ptr<testing::Screenshot> screenshot) {
90 if (!screenshot || !screenshot->GetBytes()) {
91 FML_LOG(ERROR) << "Failed to collect screenshot for test " << GetTestName();
92 return false;
93 }
94 std::string test_name = GetTestName();
95 std::string filename = GetGoldenFilename();
96 testing::GoldenDigest::Instance()->AddImage(
97 test_name, filename, screenshot->GetWidth(), screenshot->GetHeight());
98 if (!screenshot->WriteToPNG(
99 testing::WorkingDirectory::Instance()->GetFilenamePath(filename))) {
100 FML_LOG(ERROR) << "Failed to write screenshot to " << filename;
101 return false;
102 }
103 return true;
104}
105
106} // namespace
107
108struct GoldenPlaygroundTest::GoldenPlaygroundTestImpl {
109 std::unique_ptr<PlaygroundImpl> test_vulkan_playground;
110 std::unique_ptr<PlaygroundImpl> test_opengl_playground;
111 std::unique_ptr<testing::Screenshotter> screenshotter;
112 ISize window_size = ISize{1024, 768};
113};
114
115GoldenPlaygroundTest::GoldenPlaygroundTest()
116 : typographer_context_(TypographerContextSkia::Make()),
117 pimpl_(new GoldenPlaygroundTest::GoldenPlaygroundTestImpl()) {}
118
119GoldenPlaygroundTest::~GoldenPlaygroundTest() = default;
120
121void GoldenPlaygroundTest::SetTypographerContext(
122 std::shared_ptr<TypographerContext> typographer_context) {
123 typographer_context_ = std::move(typographer_context);
124};
125
126void GoldenPlaygroundTest::TearDown() {
127 ASSERT_FALSE(dlopen("/usr/local/lib/libMoltenVK.dylib", RTLD_NOLOAD));
128}
129
130namespace {
131bool DoesSupportWideGamutTests() {
132#ifdef __arm64__
133 return true;
134#else
135 return false;
136#endif
137}
138} // namespace
139
140void GoldenPlaygroundTest::SetUp() {
141 std::filesystem::path testing_assets_path =
143 std::filesystem::path target_path = testing_assets_path.parent_path()
144 .parent_path()
145 .parent_path()
146 .parent_path();
147 std::filesystem::path icd_path = target_path / "vk_swiftshader_icd.json";
148 setenv("VK_ICD_FILENAMES", icd_path.c_str(), 1);
149
150 std::string test_name = GetTestName();
151 bool enable_wide_gamut = test_name.find("WideGamut_") != std::string::npos;
152 switch (GetParam()) {
153 case PlaygroundBackend::kMetal:
154 if (!DoesSupportWideGamutTests()) {
155 GTEST_SKIP_(
156 "This metal device doesn't support wide gamut golden tests.");
157 }
158 pimpl_->screenshotter =
159 std::make_unique<testing::MetalScreenshotter>(enable_wide_gamut);
160 break;
161 case PlaygroundBackend::kVulkan: {
162 if (enable_wide_gamut) {
163 GTEST_SKIP_("Vulkan doesn't support wide gamut golden tests.");
164 }
165 const std::unique_ptr<PlaygroundImpl>& playground =
166 GetSharedVulkanPlayground(/*enable_validations=*/true);
167 pimpl_->screenshotter =
168 std::make_unique<testing::VulkanScreenshotter>(playground);
169 break;
170 }
171 case PlaygroundBackend::kOpenGLES: {
172 if (enable_wide_gamut) {
173 GTEST_SKIP_("OpenGLES doesn't support wide gamut golden tests.");
174 }
175 FML_CHECK(::glfwInit() == GLFW_TRUE);
176 PlaygroundSwitches playground_switches;
177 playground_switches.use_angle = true;
178 pimpl_->test_opengl_playground = PlaygroundImpl::Create(
179 PlaygroundBackend::kOpenGLES, playground_switches);
180 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
181 pimpl_->test_opengl_playground);
182 break;
183 }
184 }
185
186 if (std::find(kSkipTests.begin(), kSkipTests.end(), test_name) !=
187 kSkipTests.end()) {
188 GTEST_SKIP_(
189 "GoldenPlaygroundTest doesn't support interactive playground tests "
190 "yet.");
191 }
192
193 testing::GoldenDigest::Instance()->AddDimension(
194 "gpu_string", GetContext()->DescribeGpuModel());
195}
196
197PlaygroundBackend GoldenPlaygroundTest::GetBackend() const {
198 return GetParam();
199}
200
201bool GoldenPlaygroundTest::OpenPlaygroundHere(Picture picture) {
202 AiksContext renderer(GetContext(), typographer_context_);
203
204 auto screenshot = pimpl_->screenshotter->MakeScreenshot(renderer, picture,
205 pimpl_->window_size);
206 return SaveScreenshot(std::move(screenshot));
207}
208
209bool GoldenPlaygroundTest::OpenPlaygroundHere(
210 AiksPlaygroundCallback
211 callback) { // NOLINT(performance-unnecessary-value-param)
212 AiksContext renderer(GetContext(), typographer_context_);
213
214 std::optional<Picture> picture;
215 std::unique_ptr<testing::Screenshot> screenshot;
216 for (int i = 0; i < 2; ++i) {
217 picture = callback(renderer);
218 if (!picture.has_value()) {
219 return false;
220 }
221 screenshot = pimpl_->screenshotter->MakeScreenshot(
222 renderer, picture.value(), pimpl_->window_size);
223 }
224
225 return SaveScreenshot(std::move(screenshot));
226}
227
228bool GoldenPlaygroundTest::ImGuiBegin(const char* name,
229 bool* p_open,
230 ImGuiWindowFlags flags) {
231 return false;
232}
233
234std::shared_ptr<Texture> GoldenPlaygroundTest::CreateTextureForFixture(
235 const char* fixture_name,
236 bool enable_mipmapping) const {
237 std::shared_ptr<fml::Mapping> mapping =
239 auto result = Playground::CreateTextureForMapping(GetContext(), mapping,
240 enable_mipmapping);
241 if (result) {
242 result->SetLabel(fixture_name);
243 }
244 return result;
245}
246
247RuntimeStage::Map GoldenPlaygroundTest::OpenAssetAsRuntimeStage(
248 const char* asset_name) const {
249 const std::shared_ptr<fml::Mapping> fixture =
251 if (!fixture || fixture->GetSize() == 0) {
252 return {};
253 }
254 return RuntimeStage::DecodeRuntimeStages(fixture);
255}
256
257std::shared_ptr<Context> GoldenPlaygroundTest::GetContext() const {
258 return pimpl_->screenshotter->GetPlayground().GetContext();
259}
260
261std::shared_ptr<Context> GoldenPlaygroundTest::MakeContext() const {
262 if (GetParam() == PlaygroundBackend::kMetal) {
263 /// On Metal we create a context for each test.
264 return GetContext();
265 } else if (GetParam() == PlaygroundBackend::kVulkan) {
266 bool enable_vulkan_validations = true;
267 FML_CHECK(!pimpl_->test_vulkan_playground)
268 << "We don't support creating multiple contexts for one test";
269 pimpl_->test_vulkan_playground =
270 MakeVulkanPlayground(enable_vulkan_validations);
271 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
272 pimpl_->test_vulkan_playground);
273 return pimpl_->test_vulkan_playground->GetContext();
274 } else {
275 /// On OpenGL we create a context for each test.
276 return GetContext();
277 }
278}
279
280Point GoldenPlaygroundTest::GetContentScale() const {
281 return pimpl_->screenshotter->GetPlayground().GetContentScale();
282}
283
284Scalar GoldenPlaygroundTest::GetSecondsElapsed() const {
285 return 0.0f;
286}
287
288ISize GoldenPlaygroundTest::GetWindowSize() const {
289 return pimpl_->window_size;
290}
291
292void GoldenPlaygroundTest::GoldenPlaygroundTest::SetWindowSize(ISize size) {
293 pimpl_->window_size = size;
294}
295
296fml::Status GoldenPlaygroundTest::SetCapabilities(
297 const std::shared_ptr<Capabilities>& capabilities) {
298 return pimpl_->screenshotter->GetPlayground().SetCapabilities(capabilities);
299}
300
301} // namespace impeller
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
#define GLFW_TRUE
#define FML_LOG(severity)
Definition logging.h:82
#define FML_CHECK(condition)
Definition logging.h:85
#define IMP_AIKSTEST(name)
SK_API GrDirectContext * GetContext(const SkImage *src)
sk_sp< const SkPicture > picture
Definition SkRecords.h:299
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.
Definition testing.cc:59
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
Definition switches.h:259
static const std::vector< std::string > kSkipTests
float Scalar
Definition scalar.h:18
TPoint< Scalar > Point
Definition point.h:316
TSize< int64_t > ISize
Definition size.h:138
PlaygroundBackend
Definition playground.h:29
#define ERROR(message)