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);
132 context_switch.reset();
133 surface_->ClearRenderContext();
137 view_records_.clear();
139 if (raster_thread_merger_.
get() !=
nullptr &&
148 return is_torn_down_;
153 auto found = view_records_.find(
view_id);
154 if (found != view_records_.end()) {
155 return found->second.last_draw_status;
157 return std::optional<DrawSurfaceStatus>();
162 if (raster_thread_merger_) {
163 raster_thread_merger_->
Enable();
168 if (raster_thread_merger_) {
169 raster_thread_merger_->
Disable();
177 <<
"Rasterizer::NotifyLowMemoryWarning called with no surface.";
180 auto context = surface_->GetContext();
183 <<
"Rasterizer::NotifyLowMemoryWarning called with no GrContext.";
186 auto context_switch = surface_->MakeRenderContextCurrent();
187 if (!context_switch->GetResult()) {
190 context->performDeferredCleanup(std::chrono::milliseconds(0));
195 if (external_view_embedder_) {
196 external_view_embedder_->CollectView(
view_id);
202 return compositor_context_->texture_registry();
206 return surface_ ? surface_->GetContext() :
nullptr;
210 auto found = view_records_.find(
view_id);
211 if (found == view_records_.end()) {
214 auto& last_task = found->second.last_successful_task;
215 if (last_task ==
nullptr) {
218 return last_task->layer_tree.get();
222 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder) {
226 std::vector<std::unique_ptr<LayerTreeTask>> tasks;
227 for (
auto& [
view_id, view_record] : view_records_) {
228 if (view_record.last_successful_task) {
229 tasks.push_back(std::move(view_record.last_successful_task));
236 DoDrawResult result =
237 DrawToSurfaces(*frame_timings_recorder, std::move(tasks));
240 if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) {
241 bool should_resubmit_frame = ShouldResubmitFrame(result);
242 external_view_embedder_->SetUsedThisFrame(
false);
243 external_view_embedder_->EndFrame(should_resubmit_frame,
244 raster_thread_merger_);
250 if (raster_thread_merger_ &&
259 DoDrawResult draw_result;
260 FramePipeline::Consumer consumer = [&draw_result,
261 this](std::unique_ptr<FrameItem> item) {
262 draw_result = DoDraw(std::move(item->frame_timings_recorder),
263 std::move(item->layer_tree_tasks));
273 bool should_resubmit_frame = ShouldResubmitFrame(draw_result);
274 if (should_resubmit_frame) {
276 auto front_continuation =
pipeline->ProduceIfEmpty();
278 front_continuation.Complete(std::move(draw_result.resubmitted_item));
282 }
else if (draw_result.status == DoDrawStatus::kEnqueuePipeline) {
287 if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) {
288 external_view_embedder_->SetUsedThisFrame(
false);
289 external_view_embedder_->EndFrame(should_resubmit_frame,
290 raster_thread_merger_);
295 switch (consume_result) {
298 [weak_this = weak_factory_.GetWeakPtr(),
pipeline]() {
300 weak_this->Draw(pipeline);
309 return ToDrawStatus(draw_result.status);
312bool Rasterizer::ShouldResubmitFrame(
const DoDrawResult& result) {
313 if (result.resubmitted_item) {
314 FML_CHECK(!result.resubmitted_item->layer_tree_tasks.empty());
320DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) {
322 case DoDrawStatus::kEnqueuePipeline:
323 return DrawStatus::kDone;
324 case DoDrawStatus::kNotSetUp:
325 return DrawStatus::kNotSetUp;
326 case DoDrawStatus::kGpuUnavailable:
327 return DrawStatus::kGpuUnavailable;
328 case DoDrawStatus::kDone:
329 return DrawStatus::kDone;
336std::unique_ptr<SnapshotDelegate::GpuImageResult> MakeBitmapImage(
337 const sk_sp<DisplayList>& display_list,
338 const SkImageInfo& image_info) {
345 if (image_info.width() > 16384 || image_info.height() > 16384) {
346 return std::make_unique<SnapshotDelegate::GpuImageResult>(
347 GrBackendTexture(),
nullptr,
nullptr,
348 "unable to create bitmap render target at specified size " +
349 std::to_string(image_info.width()) +
"x" +
350 std::to_string(image_info.height()));
353 sk_sp<SkSurface>
surface = SkSurfaces::Raster(image_info);
354 auto canvas = DlSkCanvasAdapter(
surface->getCanvas());
355 canvas.Clear(DlColor::kTransparent());
356 canvas.DrawDisplayList(display_list);
359 return std::make_unique<SnapshotDelegate::GpuImageResult>(
360 GrBackendTexture(),
nullptr,
image,
361 image ?
"" :
"Unable to create image");
366std::unique_ptr<Rasterizer::GpuImageResult> Rasterizer::MakeSkiaGpuImage(
367 sk_sp<DisplayList> display_list,
368 const SkImageInfo& image_info) {
370 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
376 std::unique_ptr<SnapshotDelegate::GpuImageResult> result;
377 delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
379 .SetIfTrue([&result, &image_info, &display_list] {
382 result = MakeBitmapImage(display_list, image_info);
384 .SetIfFalse([&result, &image_info, &display_list,
386 gpu_image_behavior = gpu_image_behavior_] {
388 gpu_image_behavior == MakeGpuImageBehavior::kBitmap) {
391 result = MakeBitmapImage(display_list, image_info);
395 auto context_switch =
surface->MakeRenderContextCurrent();
396 if (!context_switch->GetResult()) {
397 result = MakeBitmapImage(display_list, image_info);
403 result = MakeBitmapImage(display_list, image_info);
408 image_info.width(), image_info.height(), image_info.colorType(),
409 skgpu::Mipmapped::kNo, GrRenderable::kYes);
411 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
412 GrBackendTexture(),
nullptr,
nullptr,
413 "unable to create texture render target at specified size " +
414 std::to_string(image_info.width()) +
"x" +
415 std::to_string(image_info.height()));
419 sk_sp<SkSurface> sk_surface = SkSurfaces::WrapBackendTexture(
421 image_info.colorType(), image_info.refColorSpace(),
nullptr);
423 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
424 GrBackendTexture(),
nullptr,
nullptr,
425 "unable to create rendering surface for image");
429 auto canvas = DlSkCanvasAdapter(sk_surface->getCanvas());
430 canvas.Clear(DlColor::kTransparent());
431 canvas.DrawDisplayList(display_list);
433 result = std::make_unique<SnapshotDelegate::GpuImageResult>(
440void Rasterizer::MakeSkiaSnapshot(sk_sp<DisplayList> display_list,
441 DlISize picture_size,
442 std::function<
void(sk_sp<SkImage>)>
callback,
443 SnapshotPixelFormat pixel_format) {
444 return snapshot_controller_->MakeSkiaSnapshot(
445 display_list, picture_size, std::move(
callback), pixel_format);
448sk_sp<SkImage> Rasterizer::MakeSkiaSnapshotSync(
449 sk_sp<DisplayList> display_list,
450 DlISize picture_size,
451 SnapshotPixelFormat pixel_format) {
452 return snapshot_controller_->MakeSkiaSnapshotSync(std::move(display_list),
453 picture_size, pixel_format);
456void Rasterizer::MakeImpellerSnapshot(
457 sk_sp<DisplayList> display_list,
458 DlISize picture_size,
459 std::function<
void(std::shared_ptr<impeller::Texture>)>
callback,
460 SnapshotPixelFormat pixel_format) {
461 return snapshot_controller_->MakeImpellerSnapshot(
462 display_list, picture_size, std::move(
callback), pixel_format);
465std::shared_ptr<impeller::Texture> Rasterizer::MakeImpellerSnapshotSync(
466 sk_sp<DisplayList> display_list,
467 DlISize picture_size,
468 SnapshotPixelFormat pixel_format) {
469 return snapshot_controller_->MakeImpellerSnapshotSync(
470 std::move(display_list), picture_size, pixel_format);
473sk_sp<SkImage> Rasterizer::ConvertToRasterImage(sk_sp<SkImage>
image) {
475 return snapshot_controller_->ConvertToRasterImage(
image);
478sk_sp<SkImage> Rasterizer::MakeSkiaTextureImage(
479 sk_sp<SkImage>
image,
480 SnapshotPixelFormat pixel_format) {
482 return snapshot_controller_->MakeSkiaTextureImage(
image, pixel_format);
485std::shared_ptr<impeller::Texture> Rasterizer::MakeImpellerTextureImage(
486 sk_sp<SkImage>
image,
487 SnapshotPixelFormat pixel_format) {
489 return snapshot_controller_->MakeImpellerTextureImage(
image, pixel_format);
493void Rasterizer::CacheRuntimeStage(
494 const std::shared_ptr<impeller::RuntimeStage>& runtime_stage) {
495 if (snapshot_controller_) {
496 snapshot_controller_->CacheRuntimeStage(runtime_stage);
501bool Rasterizer::MakeRenderContextCurrent() {
502 return snapshot_controller_->MakeRenderContextCurrent();
509Rasterizer::DoDrawResult Rasterizer::DoDraw(
510 std::unique_ptr<FrameTimingsRecorder> frame_timings_recorder,
511 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
513 "Rasterizer::DoDraw", 0,
516 .GetRasterTaskRunner()
517 ->RunsTasksOnCurrentThread());
518 frame_timings_recorder->AssertInState(FrameTimingsRecorder::State::kBuildEnd);
521 return DoDrawResult{DoDrawStatus::kDone};
524 return DoDrawResult{DoDrawStatus::kNotSetUp};
528 PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess();
529 persistent_cache->ResetStoredNewShaders();
532 DoDrawResult result =
533 DrawToSurfaces(*frame_timings_recorder, std::move(tasks));
535 FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline);
536 if (result.status == DoDrawStatus::kGpuUnavailable) {
537 return DoDrawResult{DoDrawStatus::kGpuUnavailable};
541 if (persistent_cache->IsDumpingSkp() &&
542 persistent_cache->StoredNewShaders()) {
544 ScreenshotLastLayerTree(ScreenshotType::SkiaPicture,
false);
545 persistent_cache->DumpSkp(*screenshot.data);
552 delegate_.OnFrameRasterized(frame_timings_recorder->GetRecordedTime());
556#if !defined(OS_FUCHSIA)
558 frame_timings_recorder->GetRasterEndTime();
560 frame_timings_recorder->GetVsyncTargetTime();
561 if (raster_finish_time > frame_target_time) {
564 const auto frame_budget_millis =
delegate_.GetFrameBudget().count();
565 if (latest_frame_target_time < raster_finish_time) {
566 latest_frame_target_time =
567 latest_frame_target_time +
570 const auto frame_lag =
571 (latest_frame_target_time - frame_target_time).ToMillisecondsF();
572 const int vsync_transitions_missed = round(frame_lag / frame_budget_millis);
577 latest_frame_target_time,
580 "current_frame_target_time",
581 latest_frame_target_time,
582 "vsync_transitions_missed",
583 vsync_transitions_missed
604 if (raster_thread_merger_) {
605 if (raster_thread_merger_->DecrementLease() ==
608 .status = DoDrawStatus::kEnqueuePipeline,
609 .resubmitted_item = std::move(result.resubmitted_item),
617Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces(
618 FrameTimingsRecorder& frame_timings_recorder,
619 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
622 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kBuildEnd);
625 .status = DoDrawStatus::kDone,
627 if (
surface_->AllowsDrawingWhenGpuDisabled()) {
628 result.resubmitted_item =
629 DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks));
631 delegate_.GetIsGpuDisabledSyncSwitch()->Execute(
634 result.status = DoDrawStatus::kGpuUnavailable;
636 frame_timings_recorder.RecordRasterEnd();
639 result.resubmitted_item = DrawToSurfacesUnsafe(
640 frame_timings_recorder, std::move(tasks));
643 frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kRasterEnd);
648std::unique_ptr<FrameItem> Rasterizer::DrawToSurfacesUnsafe(
649 FrameTimingsRecorder& frame_timings_recorder,
650 std::vector<std::unique_ptr<LayerTreeTask>> tasks) {
651 compositor_context_->ui_time().SetLapTime(
652 frame_timings_recorder.GetBuildDuration());
655 auto task_iter = tasks.begin();
656 while (task_iter != tasks.end()) {
657 LayerTreeTask& task = **task_iter;
658 if (
delegate_.ShouldDiscardLayerTree(task.view_id, *task.layer_tree)) {
659 EnsureViewRecord(task.view_id).last_draw_status =
660 DrawSurfaceStatus::kDiscarded;
661 task_iter = tasks.erase(task_iter);
668 frame_timings_recorder.RecordRasterEnd();
672 if (external_view_embedder_) {
673 FML_DCHECK(!external_view_embedder_->GetUsedThisFrame());
674 external_view_embedder_->SetUsedThisFrame(
true);
675 external_view_embedder_->BeginFrame(
surface_->GetContext(),
676 raster_thread_merger_);
679 std::optional<fml::TimePoint> presentation_time = std::nullopt;
685 const auto vsync_target_time = frame_timings_recorder.GetVsyncTargetTime();
687 presentation_time = vsync_target_time;
694 std::vector<std::unique_ptr<LayerTreeTask>> resubmitted_tasks;
695 for (std::unique_ptr<LayerTreeTask>& task : tasks) {
696 int64_t
view_id = task->view_id;
697 std::unique_ptr<LayerTree> layer_tree = std::move(task->layer_tree);
698 float device_pixel_ratio = task->device_pixel_ratio;
701 view_id, *layer_tree, device_pixel_ratio, presentation_time);
702 FML_DCHECK(status != DrawSurfaceStatus::kDiscarded);
704 auto& view_record = EnsureViewRecord(task->view_id);
705 view_record.last_draw_status = status;
706 if (status == DrawSurfaceStatus::kSuccess) {
707 view_record.last_successful_task = std::make_unique<LayerTreeTask>(
708 view_id, std::move(layer_tree), device_pixel_ratio);
709 }
else if (status == DrawSurfaceStatus::kRetry) {
710 resubmitted_tasks.push_back(std::make_unique<LayerTreeTask>(
711 view_id, std::move(layer_tree), device_pixel_ratio));
716 frame_timings_recorder.RecordRasterEnd(
719 FireNextFrameCallbackIfPresent();
723 surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration);
727 if (resubmitted_tasks.empty()) {
730 return std::make_unique<FrameItem>(
731 std::move(resubmitted_tasks),
732 frame_timings_recorder.CloneUntil(
733 FrameTimingsRecorder::State::kBuildEnd));
741 float device_pixel_ratio,
742 std::optional<fml::TimePoint> presentation_time) {
745 DlCanvas* embedder_root_canvas =
nullptr;
746 if (external_view_embedder_) {
747 external_view_embedder_->PrepareFlutterView(layer_tree.
frame_size(),
750 embedder_root_canvas = external_view_embedder_->GetRootCanvas();
758 if (frame ==
nullptr) {
759 return DrawSurfaceStatus::kFailed;
765 DlMatrix root_surface_transformation =
768 auto root_surface_canvas =
769 embedder_root_canvas ? embedder_root_canvas : frame->Canvas();
770 auto compositor_frame = compositor_context_->AcquireFrame(
773 external_view_embedder_.get(),
774 root_surface_transformation,
776 frame->framebuffer_info()
778 raster_thread_merger_,
781 if (compositor_frame) {
784 std::unique_ptr<FrameDamage> damage;
787 if (frame->framebuffer_info().supports_partial_repaint) {
792 bool force_full_repaint =
793 external_view_embedder_ &&
794 (!raster_thread_merger_ || raster_thread_merger_->IsMerged());
796 damage = std::make_unique<FrameDamage>();
797 auto existing_damage = frame->framebuffer_info().existing_damage;
798 if (existing_damage.has_value() && !force_full_repaint) {
799 damage->SetPreviousLayerTree(GetLastLayerTree(
view_id));
800 damage->AddAdditionalDamage(existing_damage.value());
801 damage->SetClipAlignment(
802 frame->framebuffer_info().horizontal_clip_alignment,
803 frame->framebuffer_info().vertical_clip_alignment);
807 bool ignore_raster_cache =
true;
808 if (
surface_->EnableRasterCache()) {
809 ignore_raster_cache =
false;
813 compositor_frame->Raster(layer_tree,
817 if (frame_status == RasterStatus::kSkipAndRetry) {
818 return DrawSurfaceStatus::kRetry;
821 SurfaceFrame::SubmitInfo submit_info;
822 submit_info.presentation_time = presentation_time;
824 submit_info.frame_damage = damage->GetFrameDamage();
825 submit_info.buffer_damage = damage->GetBufferDamage();
828 frame->set_submit_info(submit_info);
830 if (external_view_embedder_ &&
831 (!raster_thread_merger_ || raster_thread_merger_->IsMerged())) {
833 external_view_embedder_->SubmitFlutterView(
843 if (frame_status != RasterStatus::kResubmit) {
844 compositor_context_->raster_cache().EndFrame();
848 if (frame_status == RasterStatus::kResubmit) {
849 return DrawSurfaceStatus::kRetry;
851 FML_CHECK(frame_status == RasterStatus::kSuccess);
852 return DrawSurfaceStatus::kSuccess;
856 return DrawSurfaceStatus::kFailed;
859Rasterizer::ViewRecord& Rasterizer::EnsureViewRecord(int64_t
view_id) {
870 SkPictureRecorder recorder;
871 recorder.beginRecording(
874 DlMatrix root_surface_transformation;
879 auto frame = compositor_context.
AcquireFrame(
nullptr, &canvas,
nullptr,
880 root_surface_transformation,
881 false,
true,
nullptr,
nullptr);
882 frame->Raster(*tree,
true,
nullptr);
884#if defined(OS_FUCHSIA)
885 SkSerialProcs procs = {0};
889 SkSerialProcs procs = {0};
891 procs.fImageProc = [](SkImage* img,
void*) -> SkSerialReturnType {
892 return SkPngEncoder::Encode(
nullptr, img, SkPngEncoder::Options{});
896 return recorder.finishRecordingAsPicture()->serialize(&procs);
904 GrDirectContext* surface_context,
905 const std::shared_ptr<impeller::AiksContext>& aiks_context) {
908 DlMatrix root_surface_transformation;
914 root_surface_transformation,
919 canvas->
Clear(DlColor::kTransparent());
920 frame->Raster(*tree,
true,
nullptr);
924#if IMPELLER_SUPPORTS_RENDERING
959 return Rasterizer::ScreenshotFormat::kUnknown;
961 return Rasterizer::ScreenshotFormat::kR8G8B8A8UNormInt;
963 return Rasterizer::ScreenshotFormat::kB8G8R8A8UNormInt;
965 return Rasterizer::ScreenshotFormat::kR16G16B16A16Float;
969static std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
970ScreenshotLayerTreeAsImageImpeller(
971 const std::shared_ptr<impeller::AiksContext>& aiks_context,
976 FML_LOG(ERROR) <<
"Compressed screenshots not supported for Impeller";
977 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
980 DisplayListBuilder builder(DlRect::MakeSize(tree->
frame_size()));
988 FML_LOG(ERROR) <<
"Failed to render to texture";
989 return {
nullptr, Rasterizer::ScreenshotFormat::kUnknown};
995 texture->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
996 auto impeller_context = aiks_context->GetContext();
998 impeller_context->GetResourceAllocator()->CreateBuffer(buffer_desc);
1002 pass->AddCopy(
texture, buffer);
1003 pass->EncodeCommands();
1005 sk_sp<SkData> sk_data;
1006 auto completion = [
buffer, &buffer_desc, &sk_data,
1010 FML_LOG(ERROR) <<
"Failed to complete blit pass.";
1013 sk_data = SkData::MakeWithCopy(
buffer->OnGetContents(), buffer_desc.size);
1016 if (!impeller_context->GetCommandQueue()
1017 ->Submit({command_buffer}, completion)
1019 FML_LOG(ERROR) <<
"Failed to submit commands.";
1022 return std::make_pair(
1023 sk_data, ToScreenshotFormat(
texture->GetTextureDescriptor().format));
1027std::pair<sk_sp<SkData>, Rasterizer::ScreenshotFormat>
1028Rasterizer::ScreenshotLayerTreeAsImage(
1032#if IMPELLER_SUPPORTS_RENDERING
1033 if (
delegate_.GetSettings().enable_impeller) {
1034 return ScreenshotLayerTreeAsImageImpeller(GetAiksContext(), tree,
1035 compositor_context, compressed);
1040 FML_LOG(FATAL) <<
"Impeller opt-out unavailable.";
1041 return {
nullptr, ScreenshotFormat::kUnknown};
1043 GrDirectContext* surface_context = GetGrContext();
1046 std::unique_ptr<OffscreenSurface> snapshot_surface =
1047 std::make_unique<OffscreenSurface>(surface_context, tree->
frame_size());
1049 if (!snapshot_surface->IsValid()) {
1050 FML_LOG(ERROR) <<
"Screenshot: unable to create snapshot surface";
1051 return {
nullptr, ScreenshotFormat::kUnknown};
1055 DlCanvas* canvas = snapshot_surface->GetCanvas();
1061 auto context_switch =
surface_->MakeRenderContextCurrent();
1062 if (!context_switch->GetResult()) {
1063 FML_LOG(ERROR) <<
"Screenshot: unable to make image screenshot";
1064 return {
nullptr, ScreenshotFormat::kUnknown};
1070 return std::make_pair(snapshot_surface->GetRasterData(compressed),
1071 ScreenshotFormat::kUnknown);
1077 bool base64_encode) {
1078 if (
delegate_.GetSettings().enable_impeller &&
1079 type == ScreenshotType::SkiaPicture) {
1081 FML_LOG(ERROR) <<
"Last layer tree cannot be screenshotted as a "
1082 "SkiaPicture when using Impeller.";
1090 if (layer_tree ==
nullptr) {
1091 FML_LOG(ERROR) <<
"Last layer tree was null when screenshotting.";
1096 ScreenshotFormat::kUnknown};
1100 case ScreenshotType::SkiaPicture:
1101 format =
"ScreenshotType::SkiaPicture";
1105 case ScreenshotType::UncompressedImage:
1106 format =
"ScreenshotType::UncompressedImage";
1108 ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
false);
1110 case ScreenshotType::CompressedImage:
1111 format =
"ScreenshotType::CompressedImage";
1112 data = ScreenshotLayerTreeAsImage(layer_tree, *compositor_context_,
true);
1114 case ScreenshotType::SurfaceData: {
1122 if (
data.first ==
nullptr) {
1123 FML_LOG(ERROR) <<
"Screenshot data was null.";
1127 if (base64_encode) {
1128 size_t b64_size = Base64::EncodedSize(
data.first->size());
1129 auto b64_data = SkData::MakeUninitialized(b64_size);
1130 Base64::Encode(
data.first->data(),
data.first->size(),
1131 b64_data->writable_data());
1144void Rasterizer::SetExternalViewEmbedder(
1145 const std::shared_ptr<ExternalViewEmbedder>& view_embedder) {
1146 external_view_embedder_ = view_embedder;
1149void Rasterizer::SetSnapshotSurfaceProducer(
1150 std::unique_ptr<SnapshotSurfaceProducer> producer) {
1151 snapshot_surface_producer_ = std::move(producer);
1155 return raster_thread_merger_;
1158void Rasterizer::FireNextFrameCallbackIfPresent() {
1159 if (!next_frame_callback_) {
1163 auto callback = next_frame_callback_;
1164 next_frame_callback_ =
nullptr;
1168void Rasterizer::SetResourceCacheMaxBytes(
size_t max_bytes,
bool from_user) {
1170 user_override_resource_cache_bytes_ |= from_user;
1172 if (!from_user && user_override_resource_cache_bytes_) {
1178 max_cache_bytes_ = max_bytes;
1185 auto context_switch =
surface_->MakeRenderContextCurrent();
1186 if (!context_switch->GetResult()) {
1190 context->setResourceCacheLimit(max_bytes);
1195std::optional<size_t> Rasterizer::GetResourceCacheMaxBytes()
const {
1197 return std::nullopt;
1200 return std::nullopt;
1204 return context->getResourceCacheLimit();
1206 return std::nullopt;
1210Rasterizer::Screenshot::Screenshot() {}
1212Rasterizer::Screenshot::Screenshot(sk_sp<SkData> p_data,
1214 const std::string& p_format,
1219 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
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer
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)