Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
golden_playground_test_mac.cc File Reference

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 27 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 66 of file golden_playground_test_mac.cc.

72 {
73 // TextRotated is flakey and we can't seem to get it to stabilize on Skia
74 // Gold.
75 IMP_AIKSTEST(TextRotated),
76 // Runtime stage based tests get confused with a Metal context.
77 "impeller_Play_AiksTest_CanRenderClippedRuntimeEffects_Vulkan",
78};
79
80namespace {
81std::string GetTestName() {
82 std::string suite_name =
83 ::testing::UnitTest::GetInstance()->current_test_suite()->name();
84 std::string test_name =
85 ::testing::UnitTest::GetInstance()->current_test_info()->name();
86 std::stringstream ss;
87 ss << "impeller_" << suite_name << "_" << test_name;
88 std::string result = ss.str();
89 // Make sure there are no slashes in the test name.
90 std::replace(result.begin(), result.end(), '/', '_');
91 return result;
92}
93
94std::string GetGoldenFilename(const std::string& postfix) {
95 return GetTestName() + postfix + ".png";
96}
97} // namespace
98
99bool GoldenPlaygroundTest::SaveScreenshot(
100 std::unique_ptr<testing::Screenshot> screenshot,
101 const std::string& postfix) {
102 if (!screenshot || !screenshot->GetBytes()) {
103 FML_LOG(ERROR) << "Failed to collect screenshot for test " << GetTestName();
104 return false;
105 }
106 std::string test_name = GetTestName();
107 std::string filename = GetGoldenFilename(postfix);
108 testing::GoldenDigest::Instance()->AddImage(
109 test_name, filename, screenshot->GetWidth(), screenshot->GetHeight());
110 if (!screenshot->WriteToPNG(
111 testing::WorkingDirectory::Instance()->GetFilenamePath(filename))) {
112 FML_LOG(ERROR) << "Failed to write screenshot to " << filename;
113 return false;
114 }
115 return true;
116}
117
118struct GoldenPlaygroundTest::GoldenPlaygroundTestImpl {
119 std::unique_ptr<PlaygroundImpl> test_vulkan_playground;
120 std::unique_ptr<PlaygroundImpl> test_opengl_playground;
121 std::unique_ptr<testing::Screenshotter> screenshotter;
122 ISize window_size = ISize{1024, 768};
123};
124
125GoldenPlaygroundTest::GoldenPlaygroundTest()
126 : typographer_context_(TypographerContextSkia::Make()),
127 pimpl_(new GoldenPlaygroundTest::GoldenPlaygroundTestImpl()) {}
128
129GoldenPlaygroundTest::~GoldenPlaygroundTest() = default;
130
131void GoldenPlaygroundTest::SetTypographerContext(
132 std::shared_ptr<TypographerContext> typographer_context) {
133 typographer_context_ = std::move(typographer_context);
134};
135
136void GoldenPlaygroundTest::TearDown() {
137 ASSERT_FALSE(dlopen("/usr/local/lib/libMoltenVK.dylib", RTLD_NOLOAD));
138
139 auto context = GetContext();
140 if (context) {
141 context->DisposeThreadLocalCachedResources();
142 }
143}
144
145namespace {
146bool DoesSupportWideGamutTests() {
147#ifdef __arm64__
148 return true;
149#else
150 return false;
151#endif
152}
153} // namespace
154
155void GoldenPlaygroundTest::SetUp() {
156 std::filesystem::path testing_assets_path =
158 std::filesystem::path target_path = testing_assets_path.parent_path()
159 .parent_path()
160 .parent_path()
161 .parent_path();
162 std::filesystem::path icd_path = target_path / "vk_swiftshader_icd.json";
163 setenv("VK_ICD_FILENAMES", icd_path.c_str(), 1);
164
165 std::string test_name = GetTestName();
166 PlaygroundSwitches switches;
167 switches.enable_wide_gamut =
168 test_name.find("WideGamut_") != std::string::npos;
169 switches.flags.antialiased_lines =
170 test_name.find("ExperimentAntialiasLines_") != std::string::npos;
171 switch (GetParam()) {
172 case PlaygroundBackend::kMetalSDF:
173 switches.flags.use_sdfs = true;
174 [[fallthrough]];
175 case PlaygroundBackend::kMetal:
176 if (!DoesSupportWideGamutTests()) {
177 GTEST_SKIP()
178 << "This metal device doesn't support wide gamut golden tests.";
179 }
180 pimpl_->screenshotter =
181 std::make_unique<testing::MetalScreenshotter>(switches);
182 break;
183 case PlaygroundBackend::kVulkan: {
184 if (switches.enable_wide_gamut) {
185 GTEST_SKIP() << "Vulkan doesn't support wide gamut golden tests.";
186 }
187 if (switches.flags.antialiased_lines) {
188 GTEST_SKIP()
189 << "Vulkan doesn't support antialiased lines golden tests.";
190 }
191 const std::unique_ptr<PlaygroundImpl>& playground =
192 GetSharedVulkanPlayground(/*enable_validations=*/true);
193 pimpl_->screenshotter =
194 std::make_unique<testing::VulkanScreenshotter>(playground);
195 break;
196 }
197 case PlaygroundBackend::kOpenGLES: {
198 if (switches.enable_wide_gamut) {
199 GTEST_SKIP() << "OpenGLES doesn't support wide gamut golden tests.";
200 }
201 if (switches.flags.antialiased_lines) {
202 GTEST_SKIP()
203 << "OpenGLES doesn't support antialiased lines golden tests.";
204 }
205 FML_CHECK(::glfwInit() == GLFW_TRUE);
206 PlaygroundSwitches playground_switches;
207 playground_switches.use_angle = true;
208 pimpl_->test_opengl_playground = PlaygroundImpl::Create(
209 PlaygroundBackend::kOpenGLES, playground_switches);
210 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
211 pimpl_->test_opengl_playground);
212 break;
213 }
214 }
215
216 if (std::find(kSkipTests.begin(), kSkipTests.end(), test_name) !=
217 kSkipTests.end()) {
218 GTEST_SKIP()
219 << "GoldenPlaygroundTest doesn't support interactive playground tests "
220 "yet.";
221 }
222
223 testing::GoldenDigest::Instance()->AddDimension(
224 "gpu_string", GetContext()->DescribeGpuModel());
225}
226
227PlaygroundBackend GoldenPlaygroundTest::GetBackend() const {
228 return GetParam();
229}
230
231bool GoldenPlaygroundTest::OpenPlaygroundHere(
232 const AiksDlPlaygroundCallback& callback) {
233 AiksContext renderer(GetContext(), typographer_context_);
234
235 std::unique_ptr<testing::Screenshot> screenshot;
236 Point content_scale =
237 pimpl_->screenshotter->GetPlayground().GetContentScale();
238
239 ISize physical_window_size(
240 std::round(pimpl_->window_size.width * content_scale.x),
241 std::round(pimpl_->window_size.height * content_scale.y));
242 for (int i = 0; i < 2; ++i) {
243 auto display_list = callback();
244 auto texture =
245 DisplayListToTexture(display_list, physical_window_size, renderer);
246 screenshot = pimpl_->screenshotter->MakeScreenshot(renderer, texture);
247 }
248 return SaveScreenshot(std::move(screenshot));
249}
250
251bool GoldenPlaygroundTest::OpenPlaygroundHere(
252 const sk_sp<flutter::DisplayList>& list) {
253 return OpenPlaygroundHere([&list]() { return list; });
254}
255
256bool GoldenPlaygroundTest::OpenPlaygroundHere(
257 const Playground::SinglePassCallback& callback) {
258 AiksContext renderer(GetContext(), typographer_context_);
259 std::shared_ptr<Context> context = GetContext();
260 Point content_scale =
261 pimpl_->screenshotter->GetPlayground().GetContentScale();
262 ISize size(std::round(pimpl_->window_size.width * content_scale.x),
263 std::round(pimpl_->window_size.height * content_scale.y));
264
265 std::unique_ptr<testing::Screenshot> screenshot;
266 // Render twice so the second pass observes warmed pipeline and resource
267 // caches, matching the display list path above.
268 for (int i = 0; i < 2; ++i) {
269 RenderTargetAllocator render_target_allocator(
270 context->GetResourceAllocator());
271 RenderTarget render_target = render_target_allocator.CreateOffscreen(
272 *context, size, /*mip_count=*/1, "Golden Render Pass",
273 RenderTarget::kDefaultColorAttachmentConfig,
274 /*stencil_attachment_config=*/std::nullopt);
275 if (!render_target.IsValid()) {
276 return false;
277 }
278 std::shared_ptr<CommandBuffer> command_buffer =
279 context->CreateCommandBuffer();
280 if (!command_buffer) {
281 return false;
282 }
283 std::shared_ptr<RenderPass> render_pass =
284 command_buffer->CreateRenderPass(render_target);
285 if (!render_pass) {
286 return false;
287 }
288 if (!callback(*render_pass)) {
289 return false;
290 }
291 if (!render_pass->EncodeCommands()) {
292 return false;
293 }
294 if (!context->GetCommandQueue()->Submit({command_buffer}).ok()) {
295 return false;
296 }
297 screenshot = pimpl_->screenshotter->MakeScreenshot(
298 renderer, render_target.GetRenderTargetTexture());
299 }
300 return SaveScreenshot(std::move(screenshot));
301}
302
303bool GoldenPlaygroundTest::ImGuiBegin(const char* name,
304 bool* p_open,
305 ImGuiWindowFlags flags) {
306 return false;
307}
308
309std::shared_ptr<Texture> GoldenPlaygroundTest::CreateTextureForFixture(
310 const char* fixture_name,
311 bool enable_mipmapping) const {
312 std::shared_ptr<fml::Mapping> mapping =
314 auto result = Playground::CreateTextureForMapping(GetContext(), mapping,
315 enable_mipmapping);
316 if (result) {
317 result->SetLabel(fixture_name);
318 }
319 return result;
320}
321
322sk_sp<flutter::DlImage> GoldenPlaygroundTest::CreateDlImageForFixture(
323 const char* fixture_name,
324 bool enable_mipmapping) const {
325 std::shared_ptr<Texture> texture =
326 CreateTextureForFixture(fixture_name, enable_mipmapping);
327 return DlImageImpeller::Make(texture);
328}
329
330absl::StatusOr<RuntimeStage::Map> GoldenPlaygroundTest::OpenAssetAsRuntimeStage(
331 const char* asset_name) const {
332 const std::shared_ptr<fml::Mapping> fixture =
334 if (!fixture || fixture->GetSize() == 0) {
335 return absl::NotFoundError("Asset not found or empty.");
336 }
337 return RuntimeStage::DecodeRuntimeStages(fixture);
338}
339
340std::shared_ptr<Context> GoldenPlaygroundTest::GetContext() const {
341 if (!pimpl_->screenshotter) {
342 return nullptr;
343 }
344 return pimpl_->screenshotter->GetPlayground().GetContext();
345}
346
347std::shared_ptr<Context> GoldenPlaygroundTest::MakeContext() const {
348 if (GetParam() == PlaygroundBackend::kMetal) {
349 /// On Metal we create a context for each test.
350 return GetContext();
351 } else if (GetParam() == PlaygroundBackend::kVulkan) {
352 bool enable_vulkan_validations = true;
353 FML_CHECK(!pimpl_->test_vulkan_playground)
354 << "We don't support creating multiple contexts for one test";
355 pimpl_->test_vulkan_playground =
356 MakeVulkanPlayground(enable_vulkan_validations);
357 pimpl_->screenshotter = std::make_unique<testing::VulkanScreenshotter>(
358 pimpl_->test_vulkan_playground);
359 return pimpl_->test_vulkan_playground->GetContext();
360 } else {
361 /// On OpenGL we create a context for each test.
362 return GetContext();
363 }
364}
365
366Point GoldenPlaygroundTest::GetContentScale() const {
367 return pimpl_->screenshotter->GetPlayground().GetContentScale();
368}
369
370Scalar GoldenPlaygroundTest::GetSecondsElapsed() const {
371 return 0.0f;
372}
373
374ISize GoldenPlaygroundTest::GetWindowSize() const {
375 return pimpl_->window_size;
376}
377
378IRect GoldenPlaygroundTest::GetWindowBounds() const {
379 return IRect::MakeSize(pimpl_->window_size);
380}
381
382void GoldenPlaygroundTest::GoldenPlaygroundTest::SetWindowSize(ISize size) {
383 pimpl_->window_size = size;
384}
385
386fml::Status GoldenPlaygroundTest::SetCapabilities(
387 const std::shared_ptr<Capabilities>& capabilities) {
388 return pimpl_->screenshotter->GetPlayground().SetCapabilities(capabilities);
389}
390
391std::unique_ptr<testing::Screenshot> GoldenPlaygroundTest::MakeScreenshot(
392 const sk_sp<flutter::DisplayList>& list) {
393 AiksContext renderer(GetContext(), typographer_context_);
394 Point content_scale =
395 pimpl_->screenshotter->GetPlayground().GetContentScale();
396
397 ISize physical_window_size(
398 std::round(pimpl_->window_size.width * content_scale.x),
399 std::round(pimpl_->window_size.height * content_scale.y));
400 return pimpl_->screenshotter->MakeScreenshot(
401 renderer, DisplayListToTexture(list, physical_window_size, renderer));
402}
403
404RuntimeStageBackend GoldenPlaygroundTest::GetRuntimeStageBackend() const {
405 return pimpl_->screenshotter->GetPlayground().GetRuntimeStageBackend();
406}
407
408} // namespace impeller
#define GLFW_TRUE
FlutterDesktopBinaryReply callback
#define FML_LOG(severity)
Definition logging.h:101
#define FML_CHECK(condition)
Definition logging.h:104
#define IMP_AIKSTEST(name)
FlTexture * texture
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:58
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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
float Scalar
Definition scalar.h:19
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
TPoint< Scalar > Point
Definition point.h:426
IRect64 IRect
Definition rect.h:825
PlaygroundBackend
Definition playground.h:26
ISize64 ISize
Definition size.h:162