diff --git a/engine/src/flutter/shell/common/rasterizer.cc b/engine/src/flutter/shell/common/rasterizer.cc index 98c6699c9c1..e09a29df7f9 100644 --- a/engine/src/flutter/shell/common/rasterizer.cc +++ b/engine/src/flutter/shell/common/rasterizer.cc @@ -468,7 +468,7 @@ static sk_sp CreateSnapshotSurface(GrContext* surface_context, return SkSurface::MakeRaster(image_info); } -static sk_sp ScreenshotLayerTreeAsImage( +sk_sp Rasterizer::ScreenshotLayerTreeAsImage( flutter::LayerTree* tree, flutter::CompositorContext& compositor_context, GrContext* surface_context, @@ -502,6 +502,15 @@ static sk_sp ScreenshotLayerTreeAsImage( frame->Raster(*tree, true); canvas->flush(); + // snapshot_surface->makeImageSnapshot needs the GL context to be set if the + // render context is GL. frame->Raster() pops the gl context in platforms that + // gl context switching are used. (For example, older iOS that uses GL) We + // reset the GL context using the context switch. + auto context_switch = surface_->MakeRenderContextCurrent(); + if (!context_switch->GetResult()) { + FML_LOG(ERROR) << "Screenshot: unable to make image screenshot"; + return nullptr; + } // Prepare an image from the surface, this image may potentially be on th GPU. auto potentially_gpu_snapshot = snapshot_surface->makeImageSnapshot(); if (!potentially_gpu_snapshot) { @@ -528,7 +537,6 @@ static sk_sp ScreenshotLayerTreeAsImage( FML_LOG(ERROR) << "Screenshot: unable to obtain bitmap pixels"; return nullptr; } - return SkData::MakeWithCopy(pixmap.addr32(), pixmap.computeByteSize()); } diff --git a/engine/src/flutter/shell/common/rasterizer.h b/engine/src/flutter/shell/common/rasterizer.h index 5fe34f4f584..41772c7b4fb 100644 --- a/engine/src/flutter/shell/common/rasterizer.h +++ b/engine/src/flutter/shell/common/rasterizer.h @@ -448,6 +448,12 @@ class Rasterizer final : public SnapshotDelegate { // |SnapshotDelegate| sk_sp ConvertToRasterImage(sk_sp image) override; + sk_sp ScreenshotLayerTreeAsImage( + flutter::LayerTree* tree, + flutter::CompositorContext& compositor_context, + GrContext* surface_context, + bool compressed); + sk_sp DoMakeRasterSnapshot( SkISize size, std::function draw_callback); diff --git a/engine/src/flutter/shell/common/shell_unittests.cc b/engine/src/flutter/shell/common/shell_unittests.cc index 5318458d16b..83a3dd5df95 100644 --- a/engine/src/flutter/shell/common/shell_unittests.cc +++ b/engine/src/flutter/shell/common/shell_unittests.cc @@ -1222,5 +1222,68 @@ TEST_F(ShellTest, OnServiceProtocolGetSkSLsWorks) { fml::RemoveFilesInDirectory(temp_dir.fd()); } +TEST_F(ShellTest, RasterizerScreenshot) { + Settings settings = CreateSettingsForFixture(); + auto configuration = RunConfiguration::InferFromSettings(settings); + auto task_runner = CreateNewThread(); + TaskRunners task_runners("test", task_runner, task_runner, task_runner, + task_runner); + std::unique_ptr shell = + CreateShell(std::move(settings), std::move(task_runners)); + + ASSERT_TRUE(ValidateShell(shell.get())); + PlatformViewNotifyCreated(shell.get()); + + RunEngine(shell.get(), std::move(configuration)); + + auto latch = std::make_shared(); + + PumpOneFrame(shell.get()); + + fml::TaskRunner::RunNowOrPostTask( + shell->GetTaskRunners().GetRasterTaskRunner(), [&shell, &latch]() { + Rasterizer::Screenshot screenshot = + shell->GetRasterizer()->ScreenshotLastLayerTree( + Rasterizer::ScreenshotType::CompressedImage, true); + EXPECT_NE(screenshot.data, nullptr); + + latch->Signal(); + }); + latch->Wait(); + DestroyShell(std::move(shell), std::move(task_runners)); +} + +TEST_F(ShellTest, RasterizerMakeRasterSnapshot) { + Settings settings = CreateSettingsForFixture(); + auto configuration = RunConfiguration::InferFromSettings(settings); + auto task_runner = CreateNewThread(); + TaskRunners task_runners("test", task_runner, task_runner, task_runner, + task_runner); + std::unique_ptr shell = + CreateShell(std::move(settings), std::move(task_runners)); + + ASSERT_TRUE(ValidateShell(shell.get())); + PlatformViewNotifyCreated(shell.get()); + + RunEngine(shell.get(), std::move(configuration)); + + auto latch = std::make_shared(); + + PumpOneFrame(shell.get()); + + fml::TaskRunner::RunNowOrPostTask( + shell->GetTaskRunners().GetRasterTaskRunner(), [&shell, &latch]() { + SnapshotDelegate* delegate = + reinterpret_cast(shell->GetRasterizer().get()); + sk_sp image = delegate->MakeRasterSnapshot( + SkPicture::MakePlaceholder({0, 0, 50, 50}), SkISize::Make(50, 50)); + EXPECT_NE(image, nullptr); + + latch->Signal(); + }); + latch->Wait(); + DestroyShell(std::move(shell), std::move(task_runners)); +} + } // namespace testing } // namespace flutter