diff --git a/shell/common/BUILD.gn b/shell/common/BUILD.gn index a1c1fed6205d3..5e46a60716783 100644 --- a/shell/common/BUILD.gn +++ b/shell/common/BUILD.gn @@ -302,6 +302,11 @@ if (enable_unittests) { } else { # TODO(63837): This test is hard-coded to use a TestGLSurface so it cannot run on fuchsia. sources += [ "shell_io_manager_unittests.cc" ] + + # Swiftshader only supports x86/64. Only needed on non-Fuchsia platforms. + if (shell_enable_vulkan && (target_cpu == "x86" || target_cpu == "x64")) { + deps += [ "//third_party/swiftshader_flutter:swiftshader_vulkan" ] + } } } } diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 814c1d1bda27e..077bb33365824 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -87,13 +87,17 @@ void Rasterizer::TeardownExternalViewEmbedder() { } void Rasterizer::Teardown() { - auto context_switch = - surface_ ? surface_->MakeRenderContextCurrent() : nullptr; - if (context_switch && context_switch->GetResult()) { - compositor_context_->OnGrContextDestroyed(); + if (surface_) { + auto context_switch = surface_->MakeRenderContextCurrent(); + if (context_switch->GetResult()) { + compositor_context_->OnGrContextDestroyed(); + if (auto* context = surface_->GetContext()) { + context->purgeUnlockedResources(/*scratchResourcesOnly=*/false); + } + } + surface_.reset(); } - surface_.reset(); last_layer_tree_.reset(); if (raster_thread_merger_.get() != nullptr && diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index d0669ca2d01dc..4ae9beb937396 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -19,6 +19,7 @@ using testing::_; using testing::ByMove; +using testing::NiceMock; using testing::Return; using testing::ReturnRef; @@ -77,7 +78,7 @@ class MockExternalViewEmbedder : public ExternalViewEmbedder { } // namespace TEST(RasterizerTest, create) { - MockDelegate delegate; + NiceMock delegate; auto rasterizer = std::make_unique(delegate); EXPECT_TRUE(rasterizer != nullptr); } @@ -106,10 +107,10 @@ TEST(RasterizerTest, drawEmptyPipeline) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); EXPECT_CALL(*surface, MakeRenderContextCurrent()) .WillOnce(Return(ByMove(std::make_unique(true)))); rasterizer->Setup(std::move(surface)); @@ -133,15 +134,15 @@ TEST(RasterizerTest, thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); SurfaceFrame::FramebufferInfo framebuffer_info; @@ -200,14 +201,14 @@ TEST( thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); - std::shared_ptr external_view_embedder = - std::make_shared(); + auto surface = std::make_unique>(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging) .WillRepeatedly(Return(true)); @@ -265,16 +266,16 @@ TEST( thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); SurfaceFrame::FramebufferInfo framebuffer_info; @@ -329,16 +330,16 @@ TEST(RasterizerTest, thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); SurfaceFrame::FramebufferInfo framebuffer_info; @@ -402,13 +403,13 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); auto rasterizer = std::make_unique(delegate); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); EXPECT_CALL( @@ -445,17 +446,17 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); EXPECT_CALL(*surface, MakeRenderContextCurrent()) .WillOnce(Return(ByMove(std::make_unique(true)))); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); rasterizer->Setup(std::move(surface)); @@ -500,17 +501,17 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); EXPECT_CALL(*surface, MakeRenderContextCurrent()) .WillOnce(Return(ByMove(std::make_unique(true)))); - std::shared_ptr external_view_embedder = - std::make_shared(); + std::shared_ptr> external_view_embedder = + std::make_shared>(); rasterizer->SetExternalViewEmbedder(external_view_embedder); rasterizer->Setup(std::move(surface)); @@ -543,13 +544,13 @@ TEST(RasterizerTest, thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); auto is_gpu_disabled_sync_switch = std::make_shared(false); @@ -597,12 +598,12 @@ TEST( thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); auto is_gpu_disabled_sync_switch = std::make_shared(true); @@ -652,12 +653,12 @@ TEST( thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); auto is_gpu_disabled_sync_switch = std::make_shared(false); @@ -706,12 +707,12 @@ TEST( thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); EXPECT_CALL(delegate, OnFrameRasterized(_)).Times(0); auto rasterizer = std::make_unique(delegate); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); auto is_gpu_disabled_sync_switch = std::make_shared(true); @@ -758,7 +759,7 @@ TEST(RasterizerTest, thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + NiceMock delegate; ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners)); fml::AutoResetWaitableEvent latch; @@ -769,7 +770,7 @@ TEST(RasterizerTest, }); latch.Wait(); - auto surface = std::make_unique(); + auto surface = std::make_unique>(); EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()) .WillRepeatedly(Return(true)); ON_CALL(*surface, AcquireFrame(SkISize())) @@ -831,6 +832,88 @@ TEST(RasterizerTest, latch.Wait(); } +TEST(RasterizerTest, TeardownFreesResourceCache) { + std::string test_name = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + ThreadHost thread_host("io.flutter.test." + test_name + ".", + ThreadHost::Type::Platform | ThreadHost::Type::RASTER | + ThreadHost::Type::IO | ThreadHost::Type::UI); + TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(), + thread_host.raster_thread->GetTaskRunner(), + thread_host.ui_thread->GetTaskRunner(), + thread_host.io_thread->GetTaskRunner()); + + NiceMock delegate; + EXPECT_CALL(delegate, GetTaskRunners()) + .WillRepeatedly(ReturnRef(task_runners)); + + auto rasterizer = std::make_unique(delegate); + auto surface = std::make_unique>(); + auto context = GrDirectContext::MakeMock(nullptr); + context->setResourceCacheLimit(0); + + EXPECT_CALL(*surface, MakeRenderContextCurrent()) + .WillRepeatedly([]() -> std::unique_ptr { + return std::make_unique(true); + }); + EXPECT_CALL(*surface, GetContext()).WillRepeatedly(Return(context.get())); + + rasterizer->Setup(std::move(surface)); + EXPECT_EQ(context->getResourceCacheLimit(), 0ul); + + rasterizer->SetResourceCacheMaxBytes(10000000, false); + EXPECT_EQ(context->getResourceCacheLimit(), 10000000ul); + EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul); + + int count = 0; + size_t bytes = 0; + context->getResourceCacheUsage(&count, &bytes); + EXPECT_EQ(bytes, 0ul); + + auto image_info = + SkImageInfo::MakeN32Premul(500, 500, SkColorSpace::MakeSRGB()); + auto sk_surface = + SkSurface::MakeRenderTarget(context.get(), SkBudgeted::kYes, image_info); + EXPECT_TRUE(sk_surface); + + SkPaint paint; + sk_surface->getCanvas()->drawPaint(paint); + sk_surface->getCanvas()->flush(); + context->flushAndSubmit(true); + + EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul); + + sk_surface.reset(); + + context->getResourceCacheUsage(&count, &bytes); + EXPECT_GT(bytes, 0ul); + EXPECT_GT(context->getResourceCachePurgeableBytes(), 0ul); + + rasterizer->Teardown(); + EXPECT_EQ(context->getResourceCachePurgeableBytes(), 0ul); +} + +TEST(RasterizerTest, TeardownNoSurface) { + std::string test_name = + ::testing::UnitTest::GetInstance()->current_test_info()->name(); + ThreadHost thread_host("io.flutter.test." + test_name + ".", + ThreadHost::Type::Platform | ThreadHost::Type::RASTER | + ThreadHost::Type::IO | ThreadHost::Type::UI); + TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(), + thread_host.raster_thread->GetTaskRunner(), + thread_host.ui_thread->GetTaskRunner(), + thread_host.io_thread->GetTaskRunner()); + + NiceMock delegate; + EXPECT_CALL(delegate, GetTaskRunners()) + .WillRepeatedly(ReturnRef(task_runners)); + + auto rasterizer = std::make_unique(delegate); + + EXPECT_TRUE(rasterizer); + rasterizer->Teardown(); +} + TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) { std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name(); @@ -841,7 +924,8 @@ TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + + NiceMock delegate; ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners)); fml::AutoResetWaitableEvent latch; @@ -920,7 +1004,8 @@ TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) { thread_host.raster_thread->GetTaskRunner(), thread_host.ui_thread->GetTaskRunner(), thread_host.io_thread->GetTaskRunner()); - MockDelegate delegate; + + NiceMock delegate; ON_CALL(delegate, GetTaskRunners()).WillByDefault(ReturnRef(task_runners)); fml::AutoResetWaitableEvent latch; diff --git a/shell/common/shell_test_platform_view_vulkan.cc b/shell/common/shell_test_platform_view_vulkan.cc index 853e621e752ab..4068a9cb2ee79 100644 --- a/shell/common/shell_test_platform_view_vulkan.cc +++ b/shell/common/shell_test_platform_view_vulkan.cc @@ -8,6 +8,16 @@ #include "flutter/shell/common/context_options.h" #include "flutter/vulkan/vulkan_utilities.h" +#if OS_FUCHSIA +#define VULKAN_SO_PATH "libvulkan.so" +#elif FML_OS_MACOSX +#define VULKAN_SO_PATH "libvk_swiftshader.dylib" +#elif FML_OS_WIN +#define VULKAN_SO_PATH "vk_swiftshader.dll" +#else +#define VULKAN_SO_PATH "libvk_swiftshader.so" +#endif + namespace flutter { namespace testing { @@ -21,7 +31,7 @@ ShellTestPlatformViewVulkan::ShellTestPlatformViewVulkan( : ShellTestPlatformView(delegate, std::move(task_runners)), create_vsync_waiter_(std::move(create_vsync_waiter)), vsync_clock_(vsync_clock), - proc_table_(fml::MakeRefCounted()), + proc_table_(fml::MakeRefCounted(VULKAN_SO_PATH)), shell_test_external_view_embedder_(shell_test_external_view_embedder) {} ShellTestPlatformViewVulkan::~ShellTestPlatformViewVulkan() = default; diff --git a/testing/run_tests.py b/testing/run_tests.py index c96a41ae1f9c1..1a6ad24550f2c 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -159,7 +159,7 @@ def BuildEngineExecutableCommand( gtest_parallel = os.path.join( buildroot_dir, 'third_party', 'gtest-parallel', 'gtest-parallel' ) - test_command = ['python', gtest_parallel] + test_command + test_command = ['python3', gtest_parallel] + test_command return test_command @@ -181,13 +181,15 @@ def RunEngineExecutable( return unstripped_exe = os.path.join(build_dir, 'exe.unstripped', executable_name) + env = os.environ.copy() # We cannot run the unstripped binaries directly when coverage is enabled. if IsLinux() and os.path.exists(unstripped_exe) and not coverage: # Some tests depend on the EGL/GLES libraries placed in the build directory. - env = os.environ.copy() env['LD_LIBRARY_PATH'] = os.path.join(build_dir, 'lib.unstripped') + elif IsMac(): + env['DYLD_LIBRARY_PATH'] = build_dir else: - env = None + env['PATH'] = build_dir + ":" + env['PATH'] print('Running %s in %s' % (executable_name, cwd)) @@ -199,8 +201,6 @@ def RunEngineExecutable( gtest=gtest, ) - if not env: - env = os.environ.copy() env['FLUTTER_BUILD_DIRECTORY'] = build_dir for key, value in extra_env.items(): env[key] = value @@ -1029,7 +1029,7 @@ def main(): variants_to_skip = ['host_release', 'host_profile'] if ('engine' in types or 'font-subset' in types) and args.variant not in variants_to_skip: - RunCmd(['python', 'test.py'], cwd=font_subset_dir) + RunCmd(['python3', 'test.py'], cwd=font_subset_dir) if __name__ == '__main__':