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::MakeRasterSnapshot(
439 sk_sp<DisplayList> display_list,
440 DlISize picture_size,
441 std::function<
void(sk_sp<DlImage>)>
callback,
442 SnapshotPixelFormat pixel_format) {
443 return snapshot_controller_->MakeRasterSnapshot(display_list, picture_size,
447sk_sp<DlImage> Rasterizer::MakeRasterSnapshotSync(
448 sk_sp<DisplayList> display_list,
449 DlISize picture_size,
450 SnapshotPixelFormat pixel_format) {
451 return snapshot_controller_->MakeRasterSnapshotSync(
452 display_list, picture_size, pixel_format);
455sk_sp<SkImage> Rasterizer::ConvertToRasterImage(sk_sp<SkImage>
image) {
457 return snapshot_controller_->ConvertToRasterImage(
image);
460sk_sp<DlImage> Rasterizer::MakeTextureImage(sk_sp<SkImage>
image,
461 SnapshotPixelFormat pixel_format) {
463 return snapshot_controller_->MakeTextureImage(
image, pixel_format);
467void Rasterizer::CacheRuntimeStage(
468 const std::shared_ptr<impeller::RuntimeStage>& runtime_stage) {
469 if (snapshot_controller_) {
470 snapshot_controller_->CacheRuntimeStage(runtime_stage);
475bool Rasterizer::MakeRenderContextCurrent() {
476 return snapshot_controller_->MakeRenderContextCurrent();
483Rasterizer::DoDrawResult Rasterizer::DoDraw(
484 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder,
485 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
487 "Rasterizer::DoDraw", 0,
490 .GetRasterTaskRunner()
491 ->RunsTasksOnCurrentThread());
492 frame_timings_recorder->AssertInState(FrameTimingsRecorder::State::kBuildEnd);
495 return DoDrawResult{DoDrawStatus::kDone};
498 return DoDrawResult{DoDrawStatus::kNotSetUp};
502 PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess();
503 persistent_cache->ResetStoredNewShaders();
506 DoDrawResult result =
507 DrawToSurfaces(*frame_timings_recorder, std::move(tasks));
509 FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline);
510 if (result.status == DoDrawStatus::kGpuUnavailable) {
511 return DoDrawResult{DoDrawStatus::kGpuUnavailable};
515 if (persistent_cache->IsDumpingSkp() &&
516 persistent_cache->StoredNewShaders()) {
518 ScreenshotLastLayerTree(ScreenshotType::SkiaPicture,
false);
519 persistent_cache->DumpSkp(*screenshot.data);
526 delegate_.OnFrameRasterized(frame_timings_recorder->GetRecordedTime());
530#if !defined(OS_FUCHSIA)
532 frame_timings_recorder->GetRasterEndTime();
534 frame_timings_recorder->GetVsyncTargetTime();
535 if (raster_finish_time > frame_target_time) {
538 const auto frame_budget_millis =
delegate_.GetFrameBudget().count();
539 if (latest_frame_target_time < raster_finish_time) {
540 latest_frame_target_time =
541 latest_frame_target_time +
544 const auto frame_lag =
545 (latest_frame_target_time - frame_target_time).ToMillisecondsF();
546 const int vsync_transitions_missed = round(frame_lag / frame_budget_millis);
551 latest_frame_target_time,
554 "current_frame_target_time",
555 latest_frame_target_time,
556 "vsync_transitions_missed",
557 vsync_transitions_missed
578 if (raster_thread_merger_) {
579 if (raster_thread_merger_->DecrementLease() ==
582 .status = DoDrawStatus::kEnqueuePipeline,
583 .resubmitted_item = std::move(result.resubmitted_item),
591Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces(
592 FrameTimingsRecorder& frame_timings_recorder,
593 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
596 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kBuildEnd);
599 .status = DoDrawStatus::kDone,
601 if (
surface_->AllowsDrawingWhenGpuDisabled()) {
602 result.resubmitted_item =
603 DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks));
605 delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
608 result.status = DoDrawStatus::kGpuUnavailable;
610 frame_timings_recorder.RecordRasterEnd();
613 result.resubmitted_item = DrawToSurfacesUnsafe(
614 frame_timings_recorder, std::move(tasks));
617 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kRasterEnd);
622std::unique_ptr<FrameItem> Rasterizer::DrawToSurfacesUnsafe(
623 FrameTimingsRecorder& frame_timings_recorder,
624 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
625 compositor_context_->ui_time().SetLapTime(
626 frame_timings_recorder.GetBuildDuration());
629 auto task_iter = tasks.begin();
630 while (task_iter != tasks.end()) {
631 LayerTreeTask& task = **task_iter;
632 if (
delegate_.ShouldDiscardLayerTree(task.view_id, *task.layer_tree)) {
633 EnsureViewRecord(task.view_id).last_draw_status =
634 DrawSurfaceStatus::kDiscarded;
635 task_iter = tasks.erase(task_iter);
642 frame_timings_recorder.RecordRasterEnd();
646 if (external_view_embedder_) {
647 FML_DCHECK(!external_view_embedder_->GetUsedThisFrame());
648 external_view_embedder_->SetUsedThisFrame(
true);
649 external_view_embedder_->BeginFrame(
surface_->GetContext(),
650 raster_thread_merger_);
653 std::optional<fml::TimePoint> presentation_time = std::nullopt;
659 const auto vsync_target_time = frame_timings_recorder.GetVsyncTargetTime();
661 presentation_time = vsync_target_time;
668 std::vector<std::unique_ptr<LayerTreeTask>> resubmitted_tasks;
669 for (std::unique_ptr<LayerTreeTask>& task : tasks) {
670 int64_t
view_id = task->view_id;
671 std::unique_ptr<LayerTree> layer_tree = std::move(task->layer_tree);
672 float device_pixel_ratio = task->device_pixel_ratio;
675 view_id, *layer_tree, device_pixel_ratio, presentation_time);
676 FML_DCHECK(status != DrawSurfaceStatus::kDiscarded);
678 auto& view_record = EnsureViewRecord(task->view_id);
679 view_record.last_draw_status = status;
680 if (status == DrawSurfaceStatus::kSuccess) {
681 view_record.last_successful_task = std::make_unique<LayerTreeTask>(
682 view_id, std::move(layer_tree), device_pixel_ratio);
683 }
else if (status == DrawSurfaceStatus::kRetry) {
684 resubmitted_tasks.push_back(std::make_unique<LayerTreeTask>(
685 view_id, std::move(layer_tree), device_pixel_ratio));
690 frame_timings_recorder.RecordRasterEnd(
693 FireNextFrameCallbackIfPresent();
697 surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration);
701 if (resubmitted_tasks.empty()) {
704 return std::make_unique<FrameItem>(
705 std::move(resubmitted_tasks),
706 frame_timings_recorder.CloneUntil(
707 FrameTimingsRecorder::State::kBuildEnd));
715 float device_pixel_ratio,
716 std::optional<fml::TimePoint> presentation_time) {
719 DlCanvas* embedder_root_canvas =
nullptr;
720 if (external_view_embedder_) {
721 external_view_embedder_->PrepareFlutterView(layer_tree.
frame_size(),
724 embedder_root_canvas = external_view_embedder_->GetRootCanvas();
732 if (frame ==
nullptr) {
733 return DrawSurfaceStatus::kFailed;
739 DlMatrix root_surface_transformation =
742 auto root_surface_canvas =
743 embedder_root_canvas ? embedder_root_canvas : frame->Canvas();
744 auto compositor_frame = compositor_context_->AcquireFrame(
747 external_view_embedder_.get(),
748 root_surface_transformation,
750 frame->framebuffer_info()
752 raster_thread_merger_,
755 if (compositor_frame) {
758 std::unique_ptr<FrameDamage> damage;
761 if (frame->framebuffer_info().supports_partial_repaint) {
766 bool force_full_repaint =
767 external_view_embedder_ &&
768 (!raster_thread_merger_ || raster_thread_merger_->IsMerged());
770 damage = std::make_unique<FrameDamage>();
771 auto existing_damage = frame->framebuffer_info().existing_damage;
772 if (existing_damage.has_value() && !force_full_repaint) {
773 damage->SetPreviousLayerTree(GetLastLayerTree(
view_id));
774 damage->AddAdditionalDamage(existing_damage.value());
775 damage->SetClipAlignment(
776 frame->framebuffer_info().horizontal_clip_alignment,
777 frame->framebuffer_info().vertical_clip_alignment);
781 bool ignore_raster_cache =
true;
782 if (
surface_->EnableRasterCache()) {
783 ignore_raster_cache =
false;
787 compositor_frame->Raster(layer_tree,
791 if (frame_status == RasterStatus::kSkipAndRetry) {
792 return DrawSurfaceStatus::kRetry;
795 SurfaceFrame::SubmitInfo submit_info;
796 submit_info.presentation_time = presentation_time;
798 submit_info.frame_damage = damage->GetFrameDamage();
799 submit_info.buffer_damage = damage->GetBufferDamage();
802 frame->set_submit_info(submit_info);
804 if (external_view_embedder_ &&
805 (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
807 external_view_embedder_->SubmitFlutterView(
817 if (frame_status != RasterStatus::kResubmit) {
818 compositor_context_->raster_cache().EndFrame();
822 if (frame_status == RasterStatus::kResubmit) {
823 return DrawSurfaceStatus::kRetry;
825 FML_CHECK(frame_status == RasterStatus::kSuccess);
826 return DrawSurfaceStatus::kSuccess;
830 return DrawSurfaceStatus::kFailed;
833Rasterizer::ViewRecord& Rasterizer::EnsureViewRecord(int64_t
view_id) {
844 SkPictureRecorder recorder;
845 recorder.beginRecording(
848 DlMatrix root_surface_transformation;
853 auto frame = compositor_context.
AcquireFrame(
nullptr, &canvas,
nullptr,
854 root_surface_transformation,
855 false,
true,
nullptr,
nullptr);
856 frame->Raster(*tree,
true,
nullptr);
858#if defined(OS_FUCHSIA)
859 SkSerialProcs procs = {0};
863 SkSerialProcs procs = {0};
865 procs.fImageProc = [](SkImage* img,
void*) -> SkSerialReturnType {
866 return SkPngEncoder::Encode(
nullptr, img, SkPngEncoder::Options{});
870 return recorder.finishRecordingAsPicture()->serialize(&procs);
878 GrDirectContext* surface_context,
879 const std::shared_ptr<impeller::AiksContext>& aiks_context) {
882 DlMatrix root_surface_transformation;
888 root_surface_transformation,
893 canvas->
Clear(DlColor::kTransparent());
894 frame->Raster(*tree,
true,
nullptr);
898#if IMPELLER_SUPPORTS_RENDERING
916 return Rasterizer::ScreenshotFormat::kUnknown;
918 return Rasterizer::ScreenshotFormat::kR8G8B8A8UNormInt;
920 return Rasterizer::ScreenshotFormat::kB8G8R8A8UNormInt;
922 return Rasterizer::ScreenshotFormat::kR16G16B16A16Float;
926static std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
927ScreenshotLayerTreeAsImageImpeller(
928 const std::shared_ptr<impeller::AiksContext>& aiks_context,
933 FML_LOG(ERROR) <<
"Compressed screenshots not supported for Impeller";
934 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
937 DisplayListBuilder builder(DlRect::MakeSize(tree->
frame_size()));
945 FML_LOG(ERROR) <<
"Failed to render to texture";
946 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
952 texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
953 auto impeller_context = aiks_context->GetContext();
955 impeller_context->GetResourceAllocator()->CreateBuffer(buffer_desc);
956 auto command_buffer = impeller_context->CreateCommandBuffer();
957 command_buffer->SetLabel(
"BlitTextureToBuffer Command Buffer");
958 auto pass = command_buffer->CreateBlitPass();
959 pass->AddCopy(
texture, buffer);
960 pass->EncodeCommands();
962 sk_sp<SkData> sk_data;
963 auto completion = [
buffer, &buffer_desc, &sk_data,
967 FML_LOG(ERROR) <<
"Failed to complete blit pass.";
970 sk_data = SkData::MakeWithCopy(
buffer->OnGetContents(), buffer_desc.size);
973 if (!impeller_context->GetCommandQueue()
974 ->Submit({command_buffer}, completion)
976 FML_LOG(ERROR) <<
"Failed to submit commands.";
979 return std::make_pair(
980 sk_data, ToScreenshotFormat(
texture->GetTextureDescriptor().format));
984std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
985Rasterizer::ScreenshotLayerTreeAsImage(
989#if IMPELLER_SUPPORTS_RENDERING
990 if (
delegate_.GetSettings().enable_impeller) {
991 return ScreenshotLayerTreeAsImageImpeller(GetAiksContext(), tree,
992 compositor_context, compressed);
997 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
998 return {
nullptr, ScreenshotFormat::kUnknown};
1000 GrDirectContext* surface_context = GetGrContext();
1003 std::unique_ptr<OffscreenSurface> snapshot_surface =
1004 std::make_unique<OffscreenSurface>(surface_context, tree->
frame_size());
1006 if (!snapshot_surface->IsValid()) {
1007 FML_LOG(ERROR) <<
"Screenshot: unable to create snapshot surface";
1008 return {
nullptr, ScreenshotFormat::kUnknown};
1012 DlCanvas* canvas = snapshot_surface->GetCanvas();
1018 auto context_switch =
surface_->MakeRenderContextCurrent();
1019 if (!context_switch->GetResult()) {
1020 FML_LOG(ERROR) <<
"Screenshot: unable to make image screenshot";
1021 return {
nullptr, ScreenshotFormat::kUnknown};
1027 return std::make_pair(snapshot_surface->GetRasterData(compressed),
1028 ScreenshotFormat::kUnknown);
1034 bool base64_encode) {
1035 if (
delegate_.GetSettings().enable_impeller &&
1036 type == ScreenshotType::SkiaPicture) {
1038 FML_LOG(ERROR) <<
"Last layer tree cannot be screenshotted as a "
1039 "SkiaPicture when using Impeller.";
1047 if (layer_tree ==
nullptr) {
1048 FML_LOG(ERROR) <<
"Last layer tree was null when screenshotting.";
1053 ScreenshotFormat::kUnknown};
1057 case ScreenshotType::SkiaPicture:
1058 format =
"ScreenshotType::SkiaPicture";
1062 case ScreenshotType::UncompressedImage:
1063 format =
"ScreenshotType::UncompressedImage";
1065 ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
false);
1067 case ScreenshotType::CompressedImage:
1068 format =
"ScreenshotType::CompressedImage";
1069 data = ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
true);
1071 case ScreenshotType::SurfaceData: {
1079 if (
data.first ==
nullptr) {
1080 FML_LOG(ERROR) <<
"Screenshot data was null.";
1084 if (base64_encode) {
1085 size_t b64_size = Base64::EncodedSize(
data.first->size());
1086 auto b64_data = SkData::MakeUninitialized(b64_size);
1087 Base64::Encode(
data.first->data(),
data.first->size(),
1088 b64_data->writable_data());
1101void Rasterizer::SetExternalViewEmbedder(
1102 const std::shared_ptr<ExternalViewEmbedder>& view_embedder) {
1103 external_view_embedder_ = view_embedder;
1106void Rasterizer::SetSnapshotSurfaceProducer(
1107 std::unique_ptr<SnapshotSurfaceProducer> producer) {
1108 snapshot_surface_producer_ = std::move(producer);
1112 return raster_thread_merger_;
1115void Rasterizer::FireNextFrameCallbackIfPresent() {
1116 if (!next_frame_callback_) {
1120 auto callback = next_frame_callback_;
1121 next_frame_callback_ =
nullptr;
1125void Rasterizer::SetResourceCacheMaxBytes(
size_t max_bytes,
bool from_user) {
1127 user_override_resource_cache_bytes_ |= from_user;
1129 if (!from_user && user_override_resource_cache_bytes_) {
1135 max_cache_bytes_ = max_bytes;
1140 GrDirectContext* context =
surface_->GetContext();
1142 auto context_switch =
surface_->MakeRenderContextCurrent();
1143 if (!context_switch->GetResult()) {
1147 context->setResourceCacheLimit(max_bytes);
1152std::optional<size_t> Rasterizer::GetResourceCacheMaxBytes()
const {
1154 return std::nullopt;
1157 return std::nullopt;
1159 GrDirectContext* context =
surface_->GetContext();
1161 return context->getResourceCacheLimit();
1163 return std::nullopt;
1167Rasterizer::Screenshot::Screenshot() {}
1169Rasterizer::Screenshot::Screenshot(sk_sp<SkData> p_data,
1171 const std::string& p_format,
1176 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 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
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.
std::shared_ptr< const fml::Mapping > data
#define TRACE_EVENT0(category_group, name)