diff --git a/common/config.gni b/common/config.gni index 6ec3e4c03e795..c587735b5063e 100644 --- a/common/config.gni +++ b/common/config.gni @@ -35,6 +35,9 @@ declare_args() { # See [go/slimpeller-dashboard](https://github.com/orgs/flutter/projects/21) # for details. slimpeller = false + + # Opt into new DL dispatcher that skips AIKS layer + experimental_canvas = false } # feature_defines_list --------------------------------------------------------- @@ -73,6 +76,10 @@ if (slimpeller) { feature_defines_list += [ "SLIMPELLER=1" ] } +if (experimental_canvas) { + feature_defines_list += [ "EXPERIMENTAL_CANVAS=1" ] +} + if (is_ios || is_mac) { flutter_cflags_objc = [ "-Werror=overriding-method-mismatch", diff --git a/impeller/display_list/dl_playground.cc b/impeller/display_list/dl_playground.cc index 97779e05cefc1..7d9712640912b 100644 --- a/impeller/display_list/dl_playground.cc +++ b/impeller/display_list/dl_playground.cc @@ -15,8 +15,6 @@ #include "third_party/skia/include/core/SkTypeface.h" #include "txt/platform.h" -#define ENABLE_EXPERIMENTAL_CANVAS false - namespace impeller { DlPlayground::DlPlayground() = default; @@ -50,7 +48,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) { auto list = callback(); -#if ENABLE_EXPERIMENTAL_CANVAS +#if EXPERIMENTAL_CANVAS TextFrameDispatcher collector(context.GetContentContext(), Matrix()); list->Dispatch(collector); diff --git a/shell/common/snapshot_controller_impeller.cc b/shell/common/snapshot_controller_impeller.cc index 697070134303a..3f926b5025bcd 100644 --- a/shell/common/snapshot_controller_impeller.cc +++ b/shell/common/snapshot_controller_impeller.cc @@ -12,6 +12,7 @@ #include "flutter/impeller/display_list/dl_image_impeller.h" #include "flutter/impeller/geometry/size.h" #include "flutter/shell/common/snapshot_controller.h" +#include "impeller/renderer/render_target.h" namespace flutter { @@ -21,37 +22,84 @@ sk_sp DoMakeRasterSnapshot( SkISize size, const std::shared_ptr& context) { TRACE_EVENT0("flutter", __FUNCTION__); + if (!context) { + return nullptr; + } + // Determine render target size. + auto max_size = context->GetContext() + ->GetResourceAllocator() + ->GetMaxTextureSizeSupported(); + double scale_factor_x = + static_cast(max_size.width) / static_cast(size.width()); + double scale_factor_y = + static_cast(max_size.height) / static_cast(size.height()); + double scale_factor = std::min({1.0, scale_factor_x, scale_factor_y}); + + auto render_target_size = impeller::ISize(size.width(), size.height()); + + // Scale down the render target size to the max supported by the + // GPU if necessary. Exceeding the max would otherwise cause a + // null result. + if (scale_factor < 1.0) { + render_target_size.width *= scale_factor; + render_target_size.height *= scale_factor; + } + +#if EXPERIMENTAL_CANVAS + // Do not use the render target cache as the lifecycle of this texture + // will outlive a particular frame. + impeller::ISize impeller_size = impeller::ISize(size.width(), size.height()); + impeller::RenderTargetAllocator render_target_allocator = + impeller::RenderTargetAllocator( + context->GetContext()->GetResourceAllocator()); + impeller::RenderTarget target; + if (context->GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) { + target = render_target_allocator.CreateOffscreenMSAA( + *context->GetContext(), // context + impeller_size, // size + /*mip_count=*/1, + "Picture Snapshot MSAA", // label + impeller::RenderTarget:: + kDefaultColorAttachmentConfigMSAA // color_attachment_config + ); + } else { + target = render_target_allocator.CreateOffscreen( + *context->GetContext(), // context + impeller_size, // size + /*mip_count=*/1, + "Picture Snapshot", // label + impeller::RenderTarget:: + kDefaultColorAttachmentConfig // color_attachment_config + ); + } + + impeller::TextFrameDispatcher collector(context->GetContentContext(), + impeller::Matrix()); + display_list->Dispatch(collector, SkIRect::MakeSize(size)); + impeller::ExperimentalDlDispatcher impeller_dispatcher( + context->GetContentContext(), target, + display_list->root_has_backdrop_filter(), + display_list->max_root_blend_mode(), + impeller::IRect::MakeSize(impeller_size)); + display_list->Dispatch(impeller_dispatcher, SkIRect::MakeSize(size)); + impeller_dispatcher.FinishRecording(); + + context->GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames(); + + return impeller::DlImageImpeller::Make(target.GetRenderTargetTexture(), + DlImage::OwningContext::kRaster); +#else impeller::DlDispatcher dispatcher; display_list->Dispatch(dispatcher); impeller::Picture picture = dispatcher.EndRecordingAsPicture(); - if (context) { - auto max_size = context->GetContext() - ->GetResourceAllocator() - ->GetMaxTextureSizeSupported(); - double scale_factor_x = - static_cast(max_size.width) / static_cast(size.width()); - double scale_factor_y = static_cast(max_size.height) / - static_cast(size.height()); - double scale_factor = - std::min(1.0, std::min(scale_factor_x, scale_factor_y)); - - auto render_target_size = impeller::ISize(size.width(), size.height()); - - // Scale down the render target size to the max supported by the - // GPU if necessary. Exceeding the max would otherwise cause a - // null result. - if (scale_factor < 1.0) { - render_target_size.width *= scale_factor; - render_target_size.height *= scale_factor; - } - - std::shared_ptr image = - picture.ToImage(*context, render_target_size); - if (image) { - return impeller::DlImageImpeller::Make(image->GetTexture(), - DlImage::OwningContext::kRaster); - } + + std::shared_ptr image = + picture.ToImage(*context, render_target_size); + if (image) { + return impeller::DlImageImpeller::Make(image->GetTexture(), + DlImage::OwningContext::kRaster); } +#endif // EXPERIMENTAL_CANVAS return nullptr; } diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm index 04a48a06c5e19..bc9bfd78d2ffb 100644 --- a/shell/gpu/gpu_surface_metal_impeller.mm +++ b/shell/gpu/gpu_surface_metal_impeller.mm @@ -17,8 +17,6 @@ static_assert(!__has_feature(objc_arc), "ARC must be disabled."); -#define ENABLE_EXPERIMENTAL_CANVAS false - namespace flutter { static std::shared_ptr CreateImpellerRenderer( @@ -165,7 +163,7 @@ impeller::IRect cull_rect = surface->coverage(); SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight()); -#if ENABLE_EXPERIMENTAL_CANVAS +#if EXPERIMENTAL_CANVAS impeller::TextFrameDispatcher collector(aiks_context->GetContentContext(), impeller::Matrix()); display_list->Dispatch(collector, sk_cull_rect); @@ -285,7 +283,7 @@ impeller::IRect cull_rect = surface->coverage(); SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight()); -#if ENABLE_EXPERIMENTAL_CANVAS +#if EXPERIMENTAL_CANVAS impeller::TextFrameDispatcher collector(aiks_context->GetContentContext(), impeller::Matrix()); display_list->Dispatch(collector, sk_cull_rect); diff --git a/shell/gpu/gpu_surface_vulkan_impeller.cc b/shell/gpu/gpu_surface_vulkan_impeller.cc index 5da0e5eb511a5..d32cef7e6ea4c 100644 --- a/shell/gpu/gpu_surface_vulkan_impeller.cc +++ b/shell/gpu/gpu_surface_vulkan_impeller.cc @@ -13,8 +13,6 @@ namespace flutter { -#define ENABLE_EXPERIMENTAL_CANVAS false - GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller( std::shared_ptr context) { if (!context || !context->IsValid()) { @@ -89,7 +87,7 @@ std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( std::move(surface), fml::MakeCopyable([&](impeller::RenderTarget& render_target) -> bool { -#if ENABLE_EXPERIMENTAL_CANVAS +#if EXPERIMENTAL_CANVAS impeller::TextFrameDispatcher collector( aiks_context->GetContentContext(), impeller::Matrix()); display_list->Dispatch(