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

Commit ad9af34

Browse files
author
Jonah Williams
authored
Include TextureLayer in contents of toImageSync (#35608)
1 parent ca48808 commit ad9af34

23 files changed

+220
-64
lines changed

flow/layers/layer_tree.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,29 +171,33 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
171171
}
172172
}
173173

174-
sk_sp<DisplayList> LayerTree::Flatten(const SkRect& bounds) {
174+
sk_sp<DisplayList> LayerTree::Flatten(
175+
const SkRect& bounds,
176+
std::shared_ptr<TextureRegistry> texture_registry,
177+
GrDirectContext* gr_context) {
175178
TRACE_EVENT0("flutter", "LayerTree::Flatten");
176179

177180
DisplayListCanvasRecorder builder(bounds);
178181

179182
MutatorsStack unused_stack;
180183
const FixedRefreshRateStopwatch unused_stopwatch;
181184
SkMatrix root_surface_transformation;
185+
182186
// No root surface transformation. So assume identity.
183187
root_surface_transformation.reset();
184188

185189
PrerollContext preroll_context{
186190
// clang-format off
187191
.raster_cache = nullptr,
188-
.gr_context = nullptr,
192+
.gr_context = gr_context,
189193
.view_embedder = nullptr,
190194
.mutators_stack = unused_stack,
191195
.dst_color_space = nullptr,
192196
.cull_rect = kGiantRect,
193197
.surface_needs_readback = false,
194198
.raster_time = unused_stopwatch,
195199
.ui_time = unused_stopwatch,
196-
.texture_registry = nullptr,
200+
.texture_registry = texture_registry,
197201
.checkerboard_offscreen_layers = false,
198202
.frame_device_pixel_ratio = device_pixel_ratio_
199203
// clang-format on
@@ -209,12 +213,12 @@ sk_sp<DisplayList> LayerTree::Flatten(const SkRect& bounds) {
209213
// clang-format off
210214
.internal_nodes_canvas = &internal_nodes_canvas,
211215
.leaf_nodes_canvas = &builder,
212-
.gr_context = nullptr,
216+
.gr_context = gr_context,
213217
.dst_color_space = nullptr,
214218
.view_embedder = nullptr,
215219
.raster_time = unused_stopwatch,
216220
.ui_time = unused_stopwatch,
217-
.texture_registry = nullptr,
221+
.texture_registry = texture_registry,
218222
.raster_cache = nullptr,
219223
.checkerboard_offscreen_layers = false,
220224
.frame_device_pixel_ratio = device_pixel_ratio_,

flow/layers/layer_tree.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <cstdint>
99
#include <memory>
1010

11+
#include "flutter/common/graphics/texture.h"
1112
#include "flutter/flow/compositor_context.h"
1213
#include "flutter/flow/layers/layer.h"
1314
#include "flutter/flow/raster_cache.h"
@@ -41,7 +42,10 @@ class LayerTree {
4142
void Paint(CompositorContext::ScopedFrame& frame,
4243
bool ignore_raster_cache = false) const;
4344

44-
sk_sp<DisplayList> Flatten(const SkRect& bounds);
45+
sk_sp<DisplayList> Flatten(
46+
const SkRect& bounds,
47+
std::shared_ptr<TextureRegistry> texture_registry = nullptr,
48+
GrDirectContext* gr_context = nullptr);
4549

4650
Layer* root_layer() const { return root_layer_.get(); }
4751

lib/ui/compositing.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class Scene extends NativeFieldWrapperClass1 {
3838
external String? _toImageSync(int width, int height, _Image outImage);
3939

4040
/// Creates a raster image representation of the current state of the scene.
41+
///
4142
/// This is a slow operation that is performed on a background thread.
4243
///
4344
/// Callers must dispose the [Image] when they are done with it. If the result

lib/ui/compositing/scene.cc

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "flutter/lib/ui/compositing/scene.h"
66

77
#include "flutter/fml/trace_event.h"
8+
#include "flutter/lib/ui/painting/display_list_deferred_image_gpu.h"
89
#include "flutter/lib/ui/painting/image.h"
910
#include "flutter/lib/ui/painting/picture.h"
1011
#include "flutter/lib/ui/ui_dart_state.h"
@@ -42,7 +43,7 @@ Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
4243
->get_window(0)
4344
->viewport_metrics();
4445

45-
layer_tree_ = std::make_unique<LayerTree>(
46+
layer_tree_ = std::make_shared<LayerTree>(
4647
SkISize::Make(viewport_metrics.physical_width,
4748
viewport_metrics.physical_height),
4849
static_cast<float>(viewport_metrics.device_pixel_ratio));
@@ -69,12 +70,7 @@ Dart_Handle Scene::toImageSync(uint32_t width,
6970
return tonic::ToDart("Scene did not contain a layer tree.");
7071
}
7172

72-
auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height));
73-
if (!picture) {
74-
return tonic::ToDart("Could not flatten scene into a layer tree.");
75-
}
76-
77-
Picture::RasterizeToImageSync(picture, width, height, raw_image_handle);
73+
Scene::RasterizeToImage(width, height, raw_image_handle);
7874
return Dart_Null();
7975
}
8076

@@ -87,15 +83,32 @@ Dart_Handle Scene::toImage(uint32_t width,
8783
return tonic::ToDart("Scene did not contain a layer tree.");
8884
}
8985

90-
auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height));
91-
if (!picture) {
92-
return tonic::ToDart("Could not flatten scene into a layer tree.");
93-
}
86+
return Picture::RasterizeLayerTreeToImage(std::move(layer_tree_), width,
87+
height, raw_image_callback);
88+
}
9489

95-
return Picture::RasterizeToImage(picture, width, height, raw_image_callback);
90+
void Scene::RasterizeToImage(uint32_t width,
91+
uint32_t height,
92+
Dart_Handle raw_image_handle) {
93+
auto* dart_state = UIDartState::Current();
94+
if (!dart_state) {
95+
return;
96+
}
97+
auto unref_queue = dart_state->GetSkiaUnrefQueue();
98+
auto snapshot_delegate = dart_state->GetSnapshotDelegate();
99+
auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
100+
101+
auto image = CanvasImage::Create();
102+
const SkImageInfo image_info = SkImageInfo::Make(
103+
width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
104+
auto dl_image = DlDeferredImageGPU::MakeFromLayerTree(
105+
image_info, std::move(layer_tree_), std::move(snapshot_delegate),
106+
std::move(raster_task_runner), std::move(unref_queue));
107+
image->set_image(dl_image);
108+
image->AssociateWithDartWrapper(raw_image_handle);
96109
}
97110

98-
std::unique_ptr<flutter::LayerTree> Scene::takeLayerTree() {
111+
std::shared_ptr<flutter::LayerTree> Scene::takeLayerTree() {
99112
return std::move(layer_tree_);
100113
}
101114

lib/ui/compositing/scene.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,34 @@ class Scene : public RefCountedDartWrappable<Scene> {
2626
bool checkerboardRasterCacheImages,
2727
bool checkerboardOffscreenLayers);
2828

29-
std::unique_ptr<flutter::LayerTree> takeLayerTree();
29+
std::shared_ptr<flutter::LayerTree> takeLayerTree();
3030

3131
Dart_Handle toImageSync(uint32_t width,
3232
uint32_t height,
3333
Dart_Handle raw_image_handle);
3434

3535
Dart_Handle toImage(uint32_t width,
3636
uint32_t height,
37-
Dart_Handle image_callback);
37+
Dart_Handle raw_image_handle);
3838

3939
void dispose();
4040

4141
private:
42-
explicit Scene(std::shared_ptr<flutter::Layer> rootLayer,
43-
uint32_t rasterizerTracingThreshold,
44-
bool checkerboardRasterCacheImages,
45-
bool checkerboardOffscreenLayers);
46-
47-
std::unique_ptr<flutter::LayerTree> layer_tree_;
42+
Scene(std::shared_ptr<flutter::Layer> rootLayer,
43+
uint32_t rasterizerTracingThreshold,
44+
bool checkerboardRasterCacheImages,
45+
bool checkerboardOffscreenLayers);
46+
47+
void RasterizeToImage(uint32_t width,
48+
uint32_t height,
49+
Dart_Handle raw_image_handle);
50+
51+
// This is a shared_ptr to support flattening the layer tree from the UI
52+
// thread onto the raster thread - allowing access to the texture registry
53+
// required to render TextureLayers.
54+
//
55+
// No longer valid after calling `takeLayerTree`.
56+
std::shared_ptr<flutter::LayerTree> layer_tree_;
4857
};
4958

5059
} // namespace flutter

lib/ui/painting/display_list_deferred_image_gpu.cc

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ sk_sp<DlDeferredImageGPU> DlDeferredImageGPU::Make(
2222
raster_task_runner));
2323
}
2424

25+
sk_sp<DlDeferredImageGPU> DlDeferredImageGPU::MakeFromLayerTree(
26+
const SkImageInfo& image_info,
27+
std::shared_ptr<LayerTree> layer_tree,
28+
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
29+
fml::RefPtr<fml::TaskRunner> raster_task_runner,
30+
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
31+
return sk_sp<DlDeferredImageGPU>(new DlDeferredImageGPU(
32+
ImageWrapper::MakeFromLayerTree(
33+
image_info, std::move(layer_tree), std::move(snapshot_delegate),
34+
raster_task_runner, std::move(unref_queue)),
35+
raster_task_runner));
36+
}
37+
2538
DlDeferredImageGPU::DlDeferredImageGPU(
2639
std::shared_ptr<ImageWrapper> image_wrapper,
2740
fml::RefPtr<fml::TaskRunner> raster_task_runner)
@@ -92,6 +105,20 @@ DlDeferredImageGPU::ImageWrapper::Make(
92105
return wrapper;
93106
}
94107

108+
std::shared_ptr<DlDeferredImageGPU::ImageWrapper>
109+
DlDeferredImageGPU::ImageWrapper::MakeFromLayerTree(
110+
const SkImageInfo& image_info,
111+
std::shared_ptr<LayerTree> layer_tree,
112+
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
113+
fml::RefPtr<fml::TaskRunner> raster_task_runner,
114+
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
115+
auto wrapper = std::shared_ptr<ImageWrapper>(
116+
new ImageWrapper(image_info, nullptr, std::move(snapshot_delegate),
117+
std::move(raster_task_runner), std::move(unref_queue)));
118+
wrapper->SnapshotDisplayList(std::move(layer_tree));
119+
return wrapper;
120+
}
121+
95122
DlDeferredImageGPU::ImageWrapper::ImageWrapper(
96123
const SkImageInfo& image_info,
97124
sk_sp<DisplayList> display_list,
@@ -131,9 +158,11 @@ bool DlDeferredImageGPU::ImageWrapper::isTextureBacked() const {
131158
return texture_.isValid();
132159
}
133160

134-
void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList() {
161+
void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList(
162+
std::shared_ptr<LayerTree> layer_tree) {
135163
fml::TaskRunner::RunNowOrPostTask(
136-
raster_task_runner_, [weak_this = weak_from_this()]() {
164+
raster_task_runner_,
165+
[weak_this = weak_from_this(), layer_tree = std::move(layer_tree)]() {
137166
auto wrapper = weak_this.lock();
138167
if (!wrapper) {
139168
return;
@@ -142,6 +171,14 @@ void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList() {
142171
if (!snapshot_delegate) {
143172
return;
144173
}
174+
if (layer_tree) {
175+
auto display_list =
176+
layer_tree->Flatten(SkRect::MakeWH(wrapper->image_info_.width(),
177+
wrapper->image_info_.height()),
178+
snapshot_delegate->GetTextureRegistry(),
179+
snapshot_delegate->GetGrContext());
180+
wrapper->display_list_ = std::move(display_list);
181+
}
145182
auto result = snapshot_delegate->MakeGpuImage(wrapper->display_list_,
146183
wrapper->image_info_);
147184
if (result->texture.isValid()) {

lib/ui/painting/display_list_deferred_image_gpu.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "flutter/common/graphics/texture.h"
1212
#include "flutter/display_list/display_list.h"
1313
#include "flutter/display_list/display_list_image.h"
14+
#include "flutter/flow/layers/layer_tree.h"
1415
#include "flutter/flow/skia_gpu_object.h"
1516
#include "flutter/fml/macros.h"
1617
#include "flutter/fml/memory/weak_ptr.h"
@@ -28,6 +29,13 @@ class DlDeferredImageGPU final : public DlImage {
2829
fml::RefPtr<fml::TaskRunner> raster_task_runner,
2930
fml::RefPtr<SkiaUnrefQueue> unref_queue);
3031

32+
static sk_sp<DlDeferredImageGPU> MakeFromLayerTree(
33+
const SkImageInfo& image_info,
34+
std::shared_ptr<LayerTree> layer_tree,
35+
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
36+
fml::RefPtr<fml::TaskRunner> raster_task_runner,
37+
fml::RefPtr<SkiaUnrefQueue> unref_queue);
38+
3139
// |DlImage|
3240
~DlDeferredImageGPU() override;
3341

@@ -73,6 +81,13 @@ class DlDeferredImageGPU final : public DlImage {
7381
fml::RefPtr<fml::TaskRunner> raster_task_runner,
7482
fml::RefPtr<SkiaUnrefQueue> unref_queue);
7583

84+
static std::shared_ptr<ImageWrapper> MakeFromLayerTree(
85+
const SkImageInfo& image_info,
86+
std::shared_ptr<LayerTree> layer_tree,
87+
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
88+
fml::RefPtr<fml::TaskRunner> raster_task_runner,
89+
fml::RefPtr<SkiaUnrefQueue> unref_queue);
90+
7691
const SkImageInfo image_info() const { return image_info_; }
7792
const GrBackendTexture& texture() const { return texture_; }
7893
bool isTextureBacked() const;
@@ -103,7 +118,11 @@ class DlDeferredImageGPU final : public DlImage {
103118
fml::RefPtr<fml::TaskRunner> raster_task_runner,
104119
fml::RefPtr<SkiaUnrefQueue> unref_queue);
105120

106-
void SnapshotDisplayList();
121+
// If a layer tree is provided, it will be flattened during the raster
122+
// thread task spwaned by this method. After being flattened into a display
123+
// list, the image wrapper will be updated to hold this display list and the
124+
// layer tree can be dropped.
125+
void SnapshotDisplayList(std::shared_ptr<LayerTree> layer_tree = nullptr);
107126

108127
// |ContextListener|
109128
void OnGrContextCreated() override;

lib/ui/painting/picture.cc

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,21 @@ Dart_Handle Picture::RasterizeToImage(sk_sp<DisplayList> display_list,
9595
Dart_Handle raw_image_callback) {
9696
return RasterizeToImage(
9797
[display_list](SkCanvas* canvas) { display_list->RenderTo(canvas); },
98-
width, height, raw_image_callback);
98+
nullptr, width, height, raw_image_callback);
99+
}
100+
101+
Dart_Handle Picture::RasterizeLayerTreeToImage(
102+
std::shared_ptr<LayerTree> layer_tree,
103+
uint32_t width,
104+
uint32_t height,
105+
Dart_Handle raw_image_callback) {
106+
return RasterizeToImage(nullptr, std::move(layer_tree), width, height,
107+
raw_image_callback);
99108
}
100109

101110
Dart_Handle Picture::RasterizeToImage(
102111
std::function<void(SkCanvas*)> draw_callback,
112+
std::shared_ptr<LayerTree> layer_tree,
103113
uint32_t width,
104114
uint32_t height,
105115
Dart_Handle raw_image_callback) {
@@ -158,10 +168,25 @@ Dart_Handle Picture::RasterizeToImage(
158168

159169
// Kick things off on the raster rask runner.
160170
fml::TaskRunner::RunNowOrPostTask(
161-
raster_task_runner, [ui_task_runner, snapshot_delegate, draw_callback,
162-
picture_bounds, ui_task] {
163-
sk_sp<SkImage> raster_image = snapshot_delegate->MakeRasterSnapshot(
164-
draw_callback, picture_bounds);
171+
raster_task_runner,
172+
[ui_task_runner, snapshot_delegate, draw_callback, picture_bounds,
173+
ui_task, layer_tree = std::move(layer_tree)] {
174+
sk_sp<SkImage> raster_image;
175+
if (layer_tree) {
176+
auto display_list = layer_tree->Flatten(
177+
SkRect::MakeWH(picture_bounds.width(), picture_bounds.height()),
178+
snapshot_delegate->GetTextureRegistry(),
179+
snapshot_delegate->GetGrContext());
180+
181+
raster_image = snapshot_delegate->MakeRasterSnapshot(
182+
[display_list](SkCanvas* canvas) {
183+
display_list->RenderTo(canvas);
184+
},
185+
picture_bounds);
186+
} else {
187+
raster_image = snapshot_delegate->MakeRasterSnapshot(draw_callback,
188+
picture_bounds);
189+
}
165190

166191
fml::TaskRunner::RunNowOrPostTask(
167192
ui_task_runner,

lib/ui/painting/picture.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define FLUTTER_LIB_UI_PAINTING_PICTURE_H_
77

88
#include "flutter/display_list/display_list.h"
9+
#include "flutter/flow/layers/layer_tree.h"
910
#include "flutter/flow/skia_gpu_object.h"
1011
#include "flutter/lib/ui/dart_wrapper.h"
1112
#include "flutter/lib/ui/painting/image.h"
@@ -51,8 +52,19 @@ class Picture : public RefCountedDartWrappable<Picture> {
5152
uint32_t height,
5253
Dart_Handle raw_image_callback);
5354

55+
static Dart_Handle RasterizeLayerTreeToImage(
56+
std::shared_ptr<LayerTree> layer_tree,
57+
uint32_t width,
58+
uint32_t height,
59+
Dart_Handle raw_image_callback);
60+
61+
// Callers may provide either a draw_callback (which should reference a
62+
// display list) or a layer tree. If a layer tree is provided, it will be
63+
// flattened on the raster thread. In this case the draw callback will be
64+
// ignored.
5465
static Dart_Handle RasterizeToImage(
5566
std::function<void(SkCanvas*)> draw_callback,
67+
std::shared_ptr<LayerTree> layer_tree,
5668
uint32_t width,
5769
uint32_t height,
5870
Dart_Handle raw_image_callback);

0 commit comments

Comments
 (0)