Make rasterizer screenshot work with gl_context_switch (flutter/engine#18850)

This commit is contained in:
Chris Yang 2020-06-10 10:00:43 -07:00 committed by GitHub
parent 389517d57e
commit c80477385d
3 changed files with 79 additions and 2 deletions

View File

@ -468,7 +468,7 @@ static sk_sp<SkSurface> CreateSnapshotSurface(GrContext* surface_context,
return SkSurface::MakeRaster(image_info);
}
static sk_sp<SkData> ScreenshotLayerTreeAsImage(
sk_sp<SkData> Rasterizer::ScreenshotLayerTreeAsImage(
flutter::LayerTree* tree,
flutter::CompositorContext& compositor_context,
GrContext* surface_context,
@ -502,6 +502,15 @@ static sk_sp<SkData> 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<SkData> ScreenshotLayerTreeAsImage(
FML_LOG(ERROR) << "Screenshot: unable to obtain bitmap pixels";
return nullptr;
}
return SkData::MakeWithCopy(pixmap.addr32(), pixmap.computeByteSize());
}

View File

@ -448,6 +448,12 @@ class Rasterizer final : public SnapshotDelegate {
// |SnapshotDelegate|
sk_sp<SkImage> ConvertToRasterImage(sk_sp<SkImage> image) override;
sk_sp<SkData> ScreenshotLayerTreeAsImage(
flutter::LayerTree* tree,
flutter::CompositorContext& compositor_context,
GrContext* surface_context,
bool compressed);
sk_sp<SkImage> DoMakeRasterSnapshot(
SkISize size,
std::function<void(SkCanvas*)> draw_callback);

View File

@ -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> 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<fml::AutoResetWaitableEvent>();
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> 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<fml::AutoResetWaitableEvent>();
PumpOneFrame(shell.get());
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetRasterTaskRunner(), [&shell, &latch]() {
SnapshotDelegate* delegate =
reinterpret_cast<Rasterizer*>(shell->GetRasterizer().get());
sk_sp<SkImage> 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