Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ba99420

Browse files
author
Jonah Williams
authored
[Impeller] implement experimental canvas in snapshot controller. (#53750)
Fixes flutter/flutter#150994 This ensures that the dart:ui API toImage and toImageSync use the experimental canvas API when the define is set. No other changes.
1 parent d3269d5 commit ba99420

File tree

5 files changed

+86
-37
lines changed

5 files changed

+86
-37
lines changed

common/config.gni

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ declare_args() {
3535
# See [go/slimpeller-dashboard](https://github.com/orgs/flutter/projects/21)
3636
# for details.
3737
slimpeller = false
38+
39+
# Opt into new DL dispatcher that skips AIKS layer
40+
experimental_canvas = false
3841
}
3942

4043
# feature_defines_list ---------------------------------------------------------
@@ -73,6 +76,10 @@ if (slimpeller) {
7376
feature_defines_list += [ "SLIMPELLER=1" ]
7477
}
7578

79+
if (experimental_canvas) {
80+
feature_defines_list += [ "EXPERIMENTAL_CANVAS=1" ]
81+
}
82+
7683
if (is_ios || is_mac) {
7784
flutter_cflags_objc = [
7885
"-Werror=overriding-method-mismatch",

impeller/display_list/dl_playground.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
#include "third_party/skia/include/core/SkTypeface.h"
1616
#include "txt/platform.h"
1717

18-
#define ENABLE_EXPERIMENTAL_CANVAS false
19-
2018
namespace impeller {
2119

2220
DlPlayground::DlPlayground() = default;
@@ -50,7 +48,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) {
5048

5149
auto list = callback();
5250

53-
#if ENABLE_EXPERIMENTAL_CANVAS
51+
#if EXPERIMENTAL_CANVAS
5452
TextFrameDispatcher collector(context.GetContentContext(), Matrix());
5553
list->Dispatch(collector);
5654

shell/common/snapshot_controller_impeller.cc

Lines changed: 75 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "flutter/impeller/display_list/dl_image_impeller.h"
1313
#include "flutter/impeller/geometry/size.h"
1414
#include "flutter/shell/common/snapshot_controller.h"
15+
#include "impeller/renderer/render_target.h"
1516

1617
namespace flutter {
1718

@@ -21,37 +22,84 @@ sk_sp<DlImage> DoMakeRasterSnapshot(
2122
SkISize size,
2223
const std::shared_ptr<impeller::AiksContext>& context) {
2324
TRACE_EVENT0("flutter", __FUNCTION__);
25+
if (!context) {
26+
return nullptr;
27+
}
28+
// Determine render target size.
29+
auto max_size = context->GetContext()
30+
->GetResourceAllocator()
31+
->GetMaxTextureSizeSupported();
32+
double scale_factor_x =
33+
static_cast<double>(max_size.width) / static_cast<double>(size.width());
34+
double scale_factor_y =
35+
static_cast<double>(max_size.height) / static_cast<double>(size.height());
36+
double scale_factor = std::min({1.0, scale_factor_x, scale_factor_y});
37+
38+
auto render_target_size = impeller::ISize(size.width(), size.height());
39+
40+
// Scale down the render target size to the max supported by the
41+
// GPU if necessary. Exceeding the max would otherwise cause a
42+
// null result.
43+
if (scale_factor < 1.0) {
44+
render_target_size.width *= scale_factor;
45+
render_target_size.height *= scale_factor;
46+
}
47+
48+
#if EXPERIMENTAL_CANVAS
49+
// Do not use the render target cache as the lifecycle of this texture
50+
// will outlive a particular frame.
51+
impeller::ISize impeller_size = impeller::ISize(size.width(), size.height());
52+
impeller::RenderTargetAllocator render_target_allocator =
53+
impeller::RenderTargetAllocator(
54+
context->GetContext()->GetResourceAllocator());
55+
impeller::RenderTarget target;
56+
if (context->GetContext()->GetCapabilities()->SupportsOffscreenMSAA()) {
57+
target = render_target_allocator.CreateOffscreenMSAA(
58+
*context->GetContext(), // context
59+
impeller_size, // size
60+
/*mip_count=*/1,
61+
"Picture Snapshot MSAA", // label
62+
impeller::RenderTarget::
63+
kDefaultColorAttachmentConfigMSAA // color_attachment_config
64+
);
65+
} else {
66+
target = render_target_allocator.CreateOffscreen(
67+
*context->GetContext(), // context
68+
impeller_size, // size
69+
/*mip_count=*/1,
70+
"Picture Snapshot", // label
71+
impeller::RenderTarget::
72+
kDefaultColorAttachmentConfig // color_attachment_config
73+
);
74+
}
75+
76+
impeller::TextFrameDispatcher collector(context->GetContentContext(),
77+
impeller::Matrix());
78+
display_list->Dispatch(collector, SkIRect::MakeSize(size));
79+
impeller::ExperimentalDlDispatcher impeller_dispatcher(
80+
context->GetContentContext(), target,
81+
display_list->root_has_backdrop_filter(),
82+
display_list->max_root_blend_mode(),
83+
impeller::IRect::MakeSize(impeller_size));
84+
display_list->Dispatch(impeller_dispatcher, SkIRect::MakeSize(size));
85+
impeller_dispatcher.FinishRecording();
86+
87+
context->GetContentContext().GetLazyGlyphAtlas()->ResetTextFrames();
88+
89+
return impeller::DlImageImpeller::Make(target.GetRenderTargetTexture(),
90+
DlImage::OwningContext::kRaster);
91+
#else
2492
impeller::DlDispatcher dispatcher;
2593
display_list->Dispatch(dispatcher);
2694
impeller::Picture picture = dispatcher.EndRecordingAsPicture();
27-
if (context) {
28-
auto max_size = context->GetContext()
29-
->GetResourceAllocator()
30-
->GetMaxTextureSizeSupported();
31-
double scale_factor_x =
32-
static_cast<double>(max_size.width) / static_cast<double>(size.width());
33-
double scale_factor_y = static_cast<double>(max_size.height) /
34-
static_cast<double>(size.height());
35-
double scale_factor =
36-
std::min(1.0, std::min(scale_factor_x, scale_factor_y));
37-
38-
auto render_target_size = impeller::ISize(size.width(), size.height());
39-
40-
// Scale down the render target size to the max supported by the
41-
// GPU if necessary. Exceeding the max would otherwise cause a
42-
// null result.
43-
if (scale_factor < 1.0) {
44-
render_target_size.width *= scale_factor;
45-
render_target_size.height *= scale_factor;
46-
}
47-
48-
std::shared_ptr<impeller::Image> image =
49-
picture.ToImage(*context, render_target_size);
50-
if (image) {
51-
return impeller::DlImageImpeller::Make(image->GetTexture(),
52-
DlImage::OwningContext::kRaster);
53-
}
95+
96+
std::shared_ptr<impeller::Image> image =
97+
picture.ToImage(*context, render_target_size);
98+
if (image) {
99+
return impeller::DlImageImpeller::Make(image->GetTexture(),
100+
DlImage::OwningContext::kRaster);
54101
}
102+
#endif // EXPERIMENTAL_CANVAS
55103

56104
return nullptr;
57105
}

shell/gpu/gpu_surface_metal_impeller.mm

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@
1717

1818
static_assert(!__has_feature(objc_arc), "ARC must be disabled.");
1919

20-
#define ENABLE_EXPERIMENTAL_CANVAS false
21-
2220
namespace flutter {
2321

2422
static std::shared_ptr<impeller::Renderer> CreateImpellerRenderer(
@@ -165,7 +163,7 @@
165163
impeller::IRect cull_rect = surface->coverage();
166164
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
167165

168-
#if ENABLE_EXPERIMENTAL_CANVAS
166+
#if EXPERIMENTAL_CANVAS
169167
impeller::TextFrameDispatcher collector(aiks_context->GetContentContext(),
170168
impeller::Matrix());
171169
display_list->Dispatch(collector, sk_cull_rect);
@@ -285,7 +283,7 @@
285283

286284
impeller::IRect cull_rect = surface->coverage();
287285
SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.GetWidth(), cull_rect.GetHeight());
288-
#if ENABLE_EXPERIMENTAL_CANVAS
286+
#if EXPERIMENTAL_CANVAS
289287
impeller::TextFrameDispatcher collector(aiks_context->GetContentContext(),
290288
impeller::Matrix());
291289
display_list->Dispatch(collector, sk_cull_rect);

shell/gpu/gpu_surface_vulkan_impeller.cc

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
namespace flutter {
1515

16-
#define ENABLE_EXPERIMENTAL_CANVAS false
17-
1816
GPUSurfaceVulkanImpeller::GPUSurfaceVulkanImpeller(
1917
std::shared_ptr<impeller::Context> context) {
2018
if (!context || !context->IsValid()) {
@@ -89,7 +87,7 @@ std::unique_ptr<SurfaceFrame> GPUSurfaceVulkanImpeller::AcquireFrame(
8987
std::move(surface),
9088
fml::MakeCopyable([&](impeller::RenderTarget& render_target)
9189
-> bool {
92-
#if ENABLE_EXPERIMENTAL_CANVAS
90+
#if EXPERIMENTAL_CANVAS
9391
impeller::TextFrameDispatcher collector(
9492
aiks_context->GetContentContext(), impeller::Matrix());
9593
display_list->Dispatch(

0 commit comments

Comments
 (0)