24#include "third_party/skia/include/core/SkColorSpace.h"
25#include "third_party/skia/include/core/SkData.h"
26#include "third_party/skia/include/core/SkImage.h"
27#include "third_party/skia/include/core/SkImageInfo.h"
28#include "third_party/skia/include/core/SkMatrix.h"
29#include "third_party/skia/include/core/SkPictureRecorder.h"
30#include "third_party/skia/include/core/SkRect.h"
31#include "third_party/skia/include/core/SkSerialProcs.h"
32#include "third_party/skia/include/core/SkSize.h"
33#include "third_party/skia/include/core/SkSurface.h"
34#include "third_party/skia/include/encode/SkPngEncoder.h"
35#include "third_party/skia/include/gpu/GpuTypes.h"
36#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
37#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
38#include "third_party/skia/include/gpu/ganesh/GrTypes.h"
39#include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
41#if IMPELLER_SUPPORTS_RENDERING
51[[maybe_unused]]
static constexpr std::chrono::milliseconds
57 gpu_image_behavior_(gpu_image_behavior),
68 return weak_factory_.GetWeakPtr();
73 return weak_factory_.GetWeakPtr();
77 std::shared_ptr<impeller::ImpellerContextFuture> impeller_context) {
78 impeller_context_ = std::move(impeller_context);
84 if (max_cache_bytes_.has_value()) {
86 user_override_resource_cache_bytes_);
89 auto context_switch = surface_->MakeRenderContextCurrent();
90 if (context_switch->GetResult()) {
91 compositor_context_->OnGrContextCreated();
94 if (external_view_embedder_ &&
95 external_view_embedder_->SupportsDynamicThreadMerging() &&
96 !raster_thread_merger_) {
97 const auto platform_id =
104 if (raster_thread_merger_) {
108 surface_->ClearRenderContext();
115 if (external_view_embedder_) {
116 external_view_embedder_->Teardown();
121 is_torn_down_ =
true;
123 auto context_switch = surface_->MakeRenderContextCurrent();
124 if (context_switch->GetResult()) {
125 compositor_context_->OnGrContextDestroyed();
127 if (
auto* context = surface_->GetContext()) {
128 context->purgeUnlockedResources(GrPurgeResourceOptions::kAllResources);
135 view_records_.clear();
137 if (raster_thread_merger_.
get() !=
nullptr &&
146 return is_torn_down_;
151 auto found = view_records_.find(
view_id);
152 if (found != view_records_.end()) {
153 return found->second.last_draw_status;
155 return std::optional<DrawSurfaceStatus>();
160 if (raster_thread_merger_) {
161 raster_thread_merger_->
Enable();
166 if (raster_thread_merger_) {
167 raster_thread_merger_->
Disable();
175 <<
"Rasterizer::NotifyLowMemoryWarning called with no surface.";
178 auto context = surface_->GetContext();
181 <<
"Rasterizer::NotifyLowMemoryWarning called with no GrContext.";
184 auto context_switch = surface_->MakeRenderContextCurrent();
185 if (!context_switch->GetResult()) {
188 context->performDeferredCleanup(std::chrono::milliseconds(0));
193 if (external_view_embedder_) {
194 external_view_embedder_->CollectView(
view_id);
200 return compositor_context_->texture_registry();
204 return surface_ ? surface_->GetContext() :
nullptr;
208 auto found = view_records_.find(
view_id);
209 if (found == view_records_.end()) {
212 auto& last_task = found->second.last_successful_task;
213 if (last_task ==
nullptr) {
216 return last_task->layer_tree.get();
220 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
224 std::vector<std::unique_ptr<LayerTreeTask>> tasks;
225 for (
auto& [
view_id, view_record] : view_records_) {
226 if (view_record.last_successful_task) {
227 tasks.push_back(std::move(view_record.last_successful_task));
234 DoDrawResult result =
235 DrawToSurfaces(*frame_timings_recorder, std::move(tasks));
238 if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) {
239 bool should_resubmit_frame = ShouldResubmitFrame(result);
240 external_view_embedder_->SetUsedThisFrame(
false);
241 external_view_embedder_->EndFrame(should_resubmit_frame,
242 raster_thread_merger_);
248 if (raster_thread_merger_ &&
257 DoDrawResult draw_result;
258 FramePipeline::Consumer consumer = [&draw_result,
259 this](std::unique_ptr<FrameItem> item) {
260 draw_result = DoDraw(std::move(item->frame_timings_recorder),
261 std::move(item->layer_tree_tasks));
271 bool should_resubmit_frame = ShouldResubmitFrame(draw_result);
272 if (should_resubmit_frame) {
274 auto front_continuation = pipeline->ProduceIfEmpty();
276 front_continuation.Complete(std::move(draw_result.resubmitted_item));
280 }
else if (draw_result.status == DoDrawStatus::kEnqueuePipeline) {
285 if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) {
286 external_view_embedder_->SetUsedThisFrame(
false);
287 external_view_embedder_->EndFrame(should_resubmit_frame,
288 raster_thread_merger_);
293 switch (consume_result) {
296 [weak_this = weak_factory_.GetWeakPtr(), pipeline]() {
298 weak_this->Draw(pipeline);
307 return ToDrawStatus(draw_result.status);
310bool Rasterizer::ShouldResubmitFrame(
const DoDrawResult& result) {
311 if (result.resubmitted_item) {
312 FML_CHECK(!result.resubmitted_item->layer_tree_tasks.empty());
318DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) {
320 case DoDrawStatus::kEnqueuePipeline:
321 return DrawStatus::kDone;
322 case DoDrawStatus::kNotSetUp:
323 return DrawStatus::kNotSetUp;
324 case DoDrawStatus::kGpuUnavailable:
325 return DrawStatus::kGpuUnavailable;
326 case DoDrawStatus::kDone:
327 return DrawStatus::kDone;
334std::unique_ptr<SnapshotDelegate::GpuImageResult> MakeBitmapImage(
335 const sk_sp<DisplayList>& display_list,
336 const SkImageInfo& image_info) {
343 if (image_info.width() > 16384 || image_info.height() > 16384) {
344 return std::make_unique<SnapshotDelegate::GpuImageResult>(
345 GrBackendTexture(),
nullptr,
nullptr,
346 "unable to create bitmap render target at specified size " +
347 std::to_string(image_info.width()) +
"x" +
348 std::to_string(image_info.height()));
351 sk_sp<SkSurface>
surface = SkSurfaces::Raster(image_info);
352 auto canvas = DlSkCanvasAdapter(
surface->getCanvas());
353 canvas.Clear(DlColor::kTransparent());
354 canvas.DrawDisplayList(display_list);
357 return std::make_unique<SnapshotDelegate::GpuImageResult>(
358 GrBackendTexture(),
nullptr,
image,
359 image ?
"" :
"Unable to create image");
364std::unique_ptr<Rasterizer::GpuImageResult> Rasterizer::MakeSkiaGpuImage(
365 sk_sp<DisplayList> display_list,
366 const SkImageInfo& image_info) {
368 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
374 std::unique_ptr<SnapshotDelegate::GpuImageResult> result;
375 delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
377 .SetIfTrue([&result, &image_info, &display_list] {
380 result = MakeBitmapImage(display_list, image_info);
382 .SetIfFalse([&result, &image_info, &display_list,
384 gpu_image_behavior = gpu_image_behavior_] {
386 gpu_image_behavior == MakeGpuImageBehavior::kBitmap) {
389 result = MakeBitmapImage(display_list, image_info);
393 auto context_switch =
surface->MakeRenderContextCurrent();
394 if (!context_switch->GetResult()) {
395 result = MakeBitmapImage(display_list, image_info);
399 auto* context =
surface->GetContext();
401 result = MakeBitmapImage(display_list, image_info);
405 GrBackendTexture
texture = context->createBackendTexture(
406 image_info.width(), image_info.height(), image_info.colorType(),
407 skgpu::Mipmapped::kNo, GrRenderable::kYes);
409 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
410 GrBackendTexture(),
nullptr,
nullptr,
411 "unable to create texture render target at specified size " +
412 std::to_string(image_info.width()) +
"x" +
413 std::to_string(image_info.height()));
417 sk_sp<SkSurface> sk_surface = SkSurfaces::WrapBackendTexture(
418 context,
texture, kTopLeft_GrSurfaceOrigin, 0,
419 image_info.colorType(), image_info.refColorSpace(),
nullptr);
421 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
422 GrBackendTexture(),
nullptr,
nullptr,
423 "unable to create rendering surface for image");
427 auto canvas = DlSkCanvasAdapter(sk_surface->getCanvas());
428 canvas.Clear(DlColor::kTransparent());
429 canvas.DrawDisplayList(display_list);
431 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
432 texture, sk_ref_sp(context),
nullptr,
"");
438void Rasterizer::MakeSkiaSnapshot(sk_sp<DisplayList> display_list,
439 DlISize picture_size,
440 std::function<
void(sk_sp<SkImage>)>
callback,
441 SnapshotPixelFormat pixel_format) {
442 return snapshot_controller_->MakeSkiaSnapshot(
443 display_list, picture_size, std::move(
callback), pixel_format);
446sk_sp<SkImage> Rasterizer::MakeSkiaSnapshotSync(
447 sk_sp<DisplayList> display_list,
448 DlISize picture_size,
449 SnapshotPixelFormat pixel_format) {
450 return snapshot_controller_->MakeSkiaSnapshotSync(std::move(display_list),
451 picture_size, pixel_format);
454void Rasterizer::MakeImpellerSnapshot(
455 sk_sp<DisplayList> display_list,
456 DlISize picture_size,
457 std::function<
void(std::shared_ptr<impeller::Texture>)>
callback,
458 SnapshotPixelFormat pixel_format) {
459 return snapshot_controller_->MakeImpellerSnapshot(
460 display_list, picture_size, std::move(
callback), pixel_format);
463std::shared_ptr<impeller::Texture> Rasterizer::MakeImpellerSnapshotSync(
464 sk_sp<DisplayList> display_list,
465 DlISize picture_size,
466 SnapshotPixelFormat pixel_format) {
467 return snapshot_controller_->MakeImpellerSnapshotSync(
468 std::move(display_list), picture_size, pixel_format);
471sk_sp<SkImage> Rasterizer::ConvertToRasterImage(sk_sp<SkImage>
image) {
473 return snapshot_controller_->ConvertToRasterImage(
image);
476sk_sp<SkImage> Rasterizer::MakeSkiaTextureImage(
477 sk_sp<SkImage>
image,
478 SnapshotPixelFormat pixel_format) {
480 return snapshot_controller_->MakeSkiaTextureImage(
image, pixel_format);
483std::shared_ptr<impeller::Texture> Rasterizer::MakeImpellerTextureImage(
484 sk_sp<SkImage>
image,
485 SnapshotPixelFormat pixel_format) {
487 return snapshot_controller_->MakeImpellerTextureImage(
image, pixel_format);
491void Rasterizer::CacheRuntimeStage(
492 const std::shared_ptr<impeller::RuntimeStage>& runtime_stage) {
493 if (snapshot_controller_) {
494 snapshot_controller_->CacheRuntimeStage(runtime_stage);
499bool Rasterizer::MakeRenderContextCurrent() {
500 return snapshot_controller_->MakeRenderContextCurrent();
507Rasterizer::DoDrawResult Rasterizer::DoDraw(
508 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder,
509 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
511 "Rasterizer::DoDraw", 0,
514 .GetRasterTaskRunner()
515 ->RunsTasksOnCurrentThread());
516 frame_timings_recorder->AssertInState(FrameTimingsRecorder::State::kBuildEnd);
519 return DoDrawResult{DoDrawStatus::kDone};
522 return DoDrawResult{DoDrawStatus::kNotSetUp};
526 PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess();
527 persistent_cache->ResetStoredNewShaders();
530 DoDrawResult result =
531 DrawToSurfaces(*frame_timings_recorder, std::move(tasks));
533 FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline);
534 if (result.status == DoDrawStatus::kGpuUnavailable) {
535 return DoDrawResult{DoDrawStatus::kGpuUnavailable};
539 if (persistent_cache->IsDumpingSkp() &&
540 persistent_cache->StoredNewShaders()) {
542 ScreenshotLastLayerTree(ScreenshotType::SkiaPicture,
false);
543 persistent_cache->DumpSkp(*screenshot.data);
550 delegate_.OnFrameRasterized(frame_timings_recorder->GetRecordedTime());
554#if !defined(OS_FUCHSIA)
556 frame_timings_recorder->GetRasterEndTime();
558 frame_timings_recorder->GetVsyncTargetTime();
559 if (raster_finish_time > frame_target_time) {
562 const auto frame_budget_millis =
delegate_.GetFrameBudget().count();
563 if (latest_frame_target_time < raster_finish_time) {
564 latest_frame_target_time =
565 latest_frame_target_time +
568 const auto frame_lag =
569 (latest_frame_target_time - frame_target_time).ToMillisecondsF();
570 const int vsync_transitions_missed = round(frame_lag / frame_budget_millis);
575 latest_frame_target_time,
578 "current_frame_target_time",
579 latest_frame_target_time,
580 "vsync_transitions_missed",
581 vsync_transitions_missed
602 if (raster_thread_merger_) {
603 if (raster_thread_merger_->DecrementLease() ==
606 .status = DoDrawStatus::kEnqueuePipeline,
607 .resubmitted_item = std::move(result.resubmitted_item),
615Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces(
616 FrameTimingsRecorder& frame_timings_recorder,
617 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
620 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kBuildEnd);
623 .status = DoDrawStatus::kDone,
625 if (
surface_->AllowsDrawingWhenGpuDisabled()) {
626 result.resubmitted_item =
627 DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks));
629 delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
632 result.status = DoDrawStatus::kGpuUnavailable;
634 frame_timings_recorder.RecordRasterEnd();
637 result.resubmitted_item = DrawToSurfacesUnsafe(
638 frame_timings_recorder, std::move(tasks));
641 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kRasterEnd);
646std::unique_ptr<FrameItem> Rasterizer::DrawToSurfacesUnsafe(
647 FrameTimingsRecorder& frame_timings_recorder,
648 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
649 compositor_context_->ui_time().SetLapTime(
650 frame_timings_recorder.GetBuildDuration());
653 auto task_iter = tasks.begin();
654 while (task_iter != tasks.end()) {
655 LayerTreeTask& task = **task_iter;
656 if (
delegate_.ShouldDiscardLayerTree(task.view_id, *task.layer_tree)) {
657 EnsureViewRecord(task.view_id).last_draw_status =
658 DrawSurfaceStatus::kDiscarded;
659 task_iter = tasks.erase(task_iter);
666 frame_timings_recorder.RecordRasterEnd();
670 if (external_view_embedder_) {
671 FML_DCHECK(!external_view_embedder_->GetUsedThisFrame());
672 external_view_embedder_->SetUsedThisFrame(
true);
673 external_view_embedder_->BeginFrame(
surface_->GetContext(),
674 raster_thread_merger_);
677 std::optional<fml::TimePoint> presentation_time = std::nullopt;
683 const auto vsync_target_time = frame_timings_recorder.GetVsyncTargetTime();
685 presentation_time = vsync_target_time;
692 std::vector<std::unique_ptr<LayerTreeTask>> resubmitted_tasks;
693 for (std::unique_ptr<LayerTreeTask>& task : tasks) {
694 int64_t
view_id = task->view_id;
695 std::unique_ptr<LayerTree> layer_tree = std::move(task->layer_tree);
696 float device_pixel_ratio = task->device_pixel_ratio;
699 view_id, *layer_tree, device_pixel_ratio, presentation_time);
700 FML_DCHECK(status != DrawSurfaceStatus::kDiscarded);
702 auto& view_record = EnsureViewRecord(task->view_id);
703 view_record.last_draw_status = status;
704 if (status == DrawSurfaceStatus::kSuccess) {
705 view_record.last_successful_task = std::make_unique<LayerTreeTask>(
706 view_id, std::move(layer_tree), device_pixel_ratio);
707 }
else if (status == DrawSurfaceStatus::kRetry) {
708 resubmitted_tasks.push_back(std::make_unique<LayerTreeTask>(
709 view_id, std::move(layer_tree), device_pixel_ratio));
714 frame_timings_recorder.RecordRasterEnd(
717 FireNextFrameCallbackIfPresent();
721 surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration);
725 if (resubmitted_tasks.empty()) {
728 return std::make_unique<FrameItem>(
729 std::move(resubmitted_tasks),
730 frame_timings_recorder.CloneUntil(
731 FrameTimingsRecorder::State::kBuildEnd));
739 float device_pixel_ratio,
740 std::optional<fml::TimePoint> presentation_time) {
743 DlCanvas* embedder_root_canvas =
nullptr;
744 if (external_view_embedder_) {
745 external_view_embedder_->PrepareFlutterView(layer_tree.
frame_size(),
748 embedder_root_canvas = external_view_embedder_->GetRootCanvas();
756 if (frame ==
nullptr) {
757 return DrawSurfaceStatus::kFailed;
763 DlMatrix root_surface_transformation =
766 auto root_surface_canvas =
767 embedder_root_canvas ? embedder_root_canvas : frame->Canvas();
768 auto compositor_frame = compositor_context_->AcquireFrame(
771 external_view_embedder_.get(),
772 root_surface_transformation,
774 frame->framebuffer_info()
776 raster_thread_merger_,
779 if (compositor_frame) {
782 std::unique_ptr<FrameDamage> damage;
785 if (frame->framebuffer_info().supports_partial_repaint) {
790 bool force_full_repaint =
791 external_view_embedder_ &&
792 (!raster_thread_merger_ || raster_thread_merger_->IsMerged());
794 damage = std::make_unique<FrameDamage>();
795 auto existing_damage = frame->framebuffer_info().existing_damage;
796 if (existing_damage.has_value() && !force_full_repaint) {
797 damage->SetPreviousLayerTree(GetLastLayerTree(
view_id));
798 damage->AddAdditionalDamage(existing_damage.value());
799 damage->SetClipAlignment(
800 frame->framebuffer_info().horizontal_clip_alignment,
801 frame->framebuffer_info().vertical_clip_alignment);
805 bool ignore_raster_cache =
true;
806 if (
surface_->EnableRasterCache()) {
807 ignore_raster_cache =
false;
811 compositor_frame->Raster(layer_tree,
815 if (frame_status == RasterStatus::kSkipAndRetry) {
816 return DrawSurfaceStatus::kRetry;
819 SurfaceFrame::SubmitInfo submit_info;
820 submit_info.presentation_time = presentation_time;
822 submit_info.frame_damage = damage->GetFrameDamage();
823 submit_info.buffer_damage = damage->GetBufferDamage();
826 frame->set_submit_info(submit_info);
828 if (external_view_embedder_ &&
829 (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
831 external_view_embedder_->SubmitFlutterView(
841 if (frame_status != RasterStatus::kResubmit) {
842 compositor_context_->raster_cache().EndFrame();
846 if (frame_status == RasterStatus::kResubmit) {
847 return DrawSurfaceStatus::kRetry;
849 FML_CHECK(frame_status == RasterStatus::kSuccess);
850 return DrawSurfaceStatus::kSuccess;
854 return DrawSurfaceStatus::kFailed;
857Rasterizer::ViewRecord& Rasterizer::EnsureViewRecord(int64_t
view_id) {
868 SkPictureRecorder recorder;
869 recorder.beginRecording(
872 DlMatrix root_surface_transformation;
877 auto frame = compositor_context.
AcquireFrame(
nullptr, &canvas,
nullptr,
878 root_surface_transformation,
879 false,
true,
nullptr,
nullptr);
880 frame->Raster(*tree,
true,
nullptr);
882#if defined(OS_FUCHSIA)
883 SkSerialProcs procs = {0};
887 SkSerialProcs procs = {0};
889 procs.fImageProc = [](SkImage* img,
void*) -> SkSerialReturnType {
890 return SkPngEncoder::Encode(
nullptr, img, SkPngEncoder::Options{});
894 return recorder.finishRecordingAsPicture()->serialize(&procs);
902 GrDirectContext* surface_context,
903 const std::shared_ptr<impeller::AiksContext>& aiks_context) {
906 DlMatrix root_surface_transformation;
912 root_surface_transformation,
917 canvas->
Clear(DlColor::kTransparent());
918 frame->Raster(*tree,
true,
nullptr);
922#if IMPELLER_SUPPORTS_RENDERING
940 return Rasterizer::ScreenshotFormat::kUnknown;
942 return Rasterizer::ScreenshotFormat::kR8G8B8A8UNormInt;
944 return Rasterizer::ScreenshotFormat::kB8G8R8A8UNormInt;
946 return Rasterizer::ScreenshotFormat::kR16G16B16A16Float;
950static std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
951ScreenshotLayerTreeAsImageImpeller(
952 const std::shared_ptr<impeller::AiksContext>& aiks_context,
957 FML_LOG(ERROR) <<
"Compressed screenshots not supported for Impeller";
958 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
961 DisplayListBuilder builder(DlRect::MakeSize(tree->
frame_size()));
969 FML_LOG(ERROR) <<
"Failed to render to texture";
970 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
976 texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
977 auto impeller_context = aiks_context->GetContext();
979 impeller_context->GetResourceAllocator()->CreateBuffer(buffer_desc);
980 auto command_buffer = impeller_context->CreateCommandBuffer();
981 command_buffer->SetLabel(
"BlitTextureToBuffer Command Buffer");
982 auto pass = command_buffer->CreateBlitPass();
983 pass->AddCopy(
texture, buffer);
984 pass->EncodeCommands();
986 sk_sp<SkData> sk_data;
987 auto completion = [
buffer, &buffer_desc, &sk_data,
991 FML_LOG(ERROR) <<
"Failed to complete blit pass.";
994 sk_data = SkData::MakeWithCopy(
buffer->OnGetContents(), buffer_desc.size);
997 if (!impeller_context->GetCommandQueue()
998 ->Submit({command_buffer}, completion)
1000 FML_LOG(ERROR) <<
"Failed to submit commands.";
1003 return std::make_pair(
1004 sk_data, ToScreenshotFormat(
texture->GetTextureDescriptor().format));
1008std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
1009Rasterizer::ScreenshotLayerTreeAsImage(
1013#if IMPELLER_SUPPORTS_RENDERING
1014 if (
delegate_.GetSettings().enable_impeller) {
1015 return ScreenshotLayerTreeAsImageImpeller(GetAiksContext(), tree,
1016 compositor_context, compressed);
1021 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
1022 return {
nullptr, ScreenshotFormat::kUnknown};
1024 GrDirectContext* surface_context = GetGrContext();
1027 std::unique_ptr<OffscreenSurface> snapshot_surface =
1028 std::make_unique<OffscreenSurface>(surface_context, tree->
frame_size());
1030 if (!snapshot_surface->IsValid()) {
1031 FML_LOG(ERROR) <<
"Screenshot: unable to create snapshot surface";
1032 return {
nullptr, ScreenshotFormat::kUnknown};
1036 DlCanvas* canvas = snapshot_surface->GetCanvas();
1042 auto context_switch =
surface_->MakeRenderContextCurrent();
1043 if (!context_switch->GetResult()) {
1044 FML_LOG(ERROR) <<
"Screenshot: unable to make image screenshot";
1045 return {
nullptr, ScreenshotFormat::kUnknown};
1051 return std::make_pair(snapshot_surface->GetRasterData(compressed),
1052 ScreenshotFormat::kUnknown);
1058 bool base64_encode) {
1059 if (
delegate_.GetSettings().enable_impeller &&
1060 type == ScreenshotType::SkiaPicture) {
1062 FML_LOG(ERROR) <<
"Last layer tree cannot be screenshotted as a "
1063 "SkiaPicture when using Impeller.";
1071 if (layer_tree ==
nullptr) {
1072 FML_LOG(ERROR) <<
"Last layer tree was null when screenshotting.";
1077 ScreenshotFormat::kUnknown};
1081 case ScreenshotType::SkiaPicture:
1082 format =
"ScreenshotType::SkiaPicture";
1086 case ScreenshotType::UncompressedImage:
1087 format =
"ScreenshotType::UncompressedImage";
1089 ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
false);
1091 case ScreenshotType::CompressedImage:
1092 format =
"ScreenshotType::CompressedImage";
1093 data = ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
true);
1095 case ScreenshotType::SurfaceData: {
1103 if (
data.first ==
nullptr) {
1104 FML_LOG(ERROR) <<
"Screenshot data was null.";
1108 if (base64_encode) {
1109 size_t b64_size = Base64::EncodedSize(
data.first->size());
1110 auto b64_data = SkData::MakeUninitialized(b64_size);
1111 Base64::Encode(
data.first->data(),
data.first->size(),
1112 b64_data->writable_data());
1125void Rasterizer::SetExternalViewEmbedder(
1126 const std::shared_ptr<ExternalViewEmbedder>& view_embedder) {
1127 external_view_embedder_ = view_embedder;
1130void Rasterizer::SetSnapshotSurfaceProducer(
1131 std::unique_ptr<SnapshotSurfaceProducer> producer) {
1132 snapshot_surface_producer_ = std::move(producer);
1136 return raster_thread_merger_;
1139void Rasterizer::FireNextFrameCallbackIfPresent() {
1140 if (!next_frame_callback_) {
1144 auto callback = next_frame_callback_;
1145 next_frame_callback_ =
nullptr;
1149void Rasterizer::SetResourceCacheMaxBytes(
size_t max_bytes,
bool from_user) {
1151 user_override_resource_cache_bytes_ |= from_user;
1153 if (!from_user && user_override_resource_cache_bytes_) {
1159 max_cache_bytes_ = max_bytes;
1164 GrDirectContext* context =
surface_->GetContext();
1166 auto context_switch =
surface_->MakeRenderContextCurrent();
1167 if (!context_switch->GetResult()) {
1171 context->setResourceCacheLimit(max_bytes);
1176std::optional<size_t> Rasterizer::GetResourceCacheMaxBytes()
const {
1178 return std::nullopt;
1181 return std::nullopt;
1183 GrDirectContext* context =
surface_->GetContext();
1185 return context->getResourceCacheLimit();
1187 return std::nullopt;
1191Rasterizer::Screenshot::Screenshot() {}
1193Rasterizer::Screenshot::Screenshot(sk_sp<SkData> p_data,
1195 const std::string& p_format,
1200 pixel_format(p_pixel_format) {}
virtual std::unique_ptr< ScopedFrame > AcquireFrame(GrDirectContext *gr_context, DlCanvas *canvas, ExternalViewEmbedder *view_embedder, const DlMatrix &root_surface_transformation, bool instrumentation_enabled, bool surface_supports_readback, fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger, impeller::AiksContext *aiks_context)
Developer-facing API for rendering anything within the engine.
void Clear(DlColor color)
Backend implementation of |DlCanvas| for |SkCanvas|.
const DlISize & frame_size() const
Used to forward events from the rasterizer to interested subsystems. Currently, the shell sets itself...
virtual const TaskRunners & GetTaskRunners() const =0
Task runners used by the shell.
virtual const fml::RefPtr< fml::RasterThreadMerger > GetParentRasterThreadMerger() const =0
The raster thread merger from parent shell's rasterizer.
bool IsTornDown()
Returns whether TearDown has been called.
flutter::LayerTree * GetLastLayerTree(int64_t view_id)
Returns the last successfully drawn layer tree for the given view, or nullptr if there isn't any....
ScreenshotType
The type of the screenshot to obtain of the previously rendered layer tree.
void DisableThreadMergerIfNeeded()
Disables the thread merger if the external view embedder supports dynamic thread merging.
~Rasterizer()
Destroys the rasterizer. This must happen on the raster task runner. All GPU resources are collected ...
Rasterizer(Delegate &delegate, MakeGpuImageBehavior gpu_image_behavior=MakeGpuImageBehavior::kGpu)
Creates a new instance of a rasterizer. Rasterizers may only be created on the raster task runner....
DrawStatus Draw(const std::shared_ptr< FramePipeline > &pipeline)
Takes the next item from the layer tree pipeline and executes the raster thread frame workload for th...
fml::TaskRunnerAffineWeakPtr< Rasterizer > GetWeakPtr() const
Gets a weak pointer to the rasterizer. The rasterizer may only be accessed on the raster task runner.
void SetResourceCacheMaxBytes(size_t max_bytes, bool from_user)
Skia has no notion of time. To work around the performance implications of this, it may cache GPU res...
void DrawLastLayerTrees(std::unique_ptr< FrameTimingsRecorder > frame_timings_recorder)
Draws the last layer trees with their last configuration. This may seem entirely redundant at first g...
MakeGpuImageBehavior
How to handle calls to MakeSkiaGpuImage.
void TeardownExternalViewEmbedder()
Releases any resource used by the external view embedder. For example, overlay surfaces or Android vi...
void EnableThreadMergerIfNeeded()
Enables the thread merger if the external view embedder supports dynamic thread merging.
fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > GetSnapshotDelegate() const
std::shared_ptr< flutter::TextureRegistry > GetTextureRegistry() override
Gets the registry of external textures currently in use by the rasterizer. These textures may be upda...
void SetImpellerContext(std::shared_ptr< impeller::ImpellerContextFuture > impeller_context)
void Teardown()
Releases the previously set up on-screen render surface and collects associated resources....
GrDirectContext * GetGrContext() override
void CollectView(int64_t view_id)
Deallocate the resources for displaying a view.
void Setup(std::unique_ptr< Surface > surface)
Rasterizers may be created well before an on-screen surface is available for rendering....
std::optional< DrawSurfaceStatus > GetLastDrawStatus(int64_t view_id)
Returns the last status of drawing the specific view.
void NotifyLowMemoryWarning() const
Notifies the rasterizer that there is a low memory situation and it must purge as many unnecessary re...
fml::RefPtr< fml::TaskRunner > GetRasterTaskRunner() const
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
static fml::RefPtr< fml::RasterThreadMerger > CreateOrShareThreadMerger(const fml::RefPtr< fml::RasterThreadMerger > &parent_merger, TaskQueueId platform_id, TaskQueueId raster_id)
void SetMergeUnmergeCallback(const fml::closure &callback)
void UnMergeNowIfLastOne()
bool IsOnRasterizingThread()
Wraps a closure that is invoked in the destructor unless released by the caller.
virtual void PostTask(const fml::closure &task) override
virtual bool RunsTasksOnCurrentThread()
virtual TaskQueueId GetTaskQueueId()
static constexpr TimeDelta FromMillisecondsF(double millis)
#define NOT_SLIMPELLER(code)
FlutterVulkanImage * image
uint32_t uint32_t * format
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_CHECK(condition)
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
#define TRACE_EVENT_WITH_FRAME_NUMBER(recorder, category_group, name, flow_id_count, flow_ids)
constexpr int64_t kFlutterImplicitViewId
SkSerialReturnType SerializeTypefaceWithData(SkTypeface *typeface, void *ctx)
impeller::Matrix DlMatrix
SkSerialReturnType SerializeTypefaceWithoutData(SkTypeface *typeface, void *ctx)
static sk_sp< SkData > ScreenshotLayerTreeAsPicture(flutter::LayerTree *tree, flutter::CompositorContext &compositor_context)
static void RenderFrameForScreenshot(flutter::CompositorContext &compositor_context, DlCanvas *canvas, flutter::LayerTree *tree, GrDirectContext *surface_context, const std::shared_ptr< impeller::AiksContext > &aiks_context)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
static constexpr std::chrono::milliseconds kSkiaCleanupExpiration(15000)
SkSerialReturnType SerializeImageWithoutData(SkImage *image, void *ctx)
void TraceEventAsyncComplete(TraceArg category_group, TraceArg name, TimePoint begin, TimePoint end)
std::chrono::duration< double, std::milli > Milliseconds
std::function< void()> closure
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.
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
flutter::DlCanvas DlCanvas
impeller::ShaderType type
A POD type used to return the screenshot data along with the size of the frame.
Screenshot()
Creates an empty screenshot.
~Screenshot()
Destroys the screenshot object and releases underlying data.
A screenshot of the surface's raw data.
Represents the 2 code paths available when calling |SyncSwitchExecute|.
A 4x4 matrix using column-major storage.
#define TRACE_EVENT0(category_group, name)