Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
picture.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <memory>
8#include <utility>
9
14#if IMPELLER_SUPPORTS_RENDERING
16#endif // IMPELLER_SUPPORTS_RENDERING
24
25namespace flutter {
26
28
30 Dart_Handle dart_handle,
31 sk_sp<DisplayList> display_list) {
32 FML_DCHECK(display_list->isUIThreadSafe());
33 auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(display_list));
34 canvas_picture->AssociateWithDartWrapper(dart_handle);
35}
36
37Picture::Picture(sk_sp<DisplayList> display_list)
38 : display_list_(std::move(display_list)) {}
39
40Picture::~Picture() = default;
41
42Dart_Handle Picture::toImage(uint32_t width,
43 uint32_t height,
44 Dart_Handle raw_image_callback) {
45 if (!display_list_) {
46 return tonic::ToDart("Picture is null");
47 }
48 return RasterizeToImage(display_list_, width, height, raw_image_callback);
49}
50
52 uint32_t height,
53 int32_t target_format,
54 Dart_Handle raw_image_handle) {
55 FML_DCHECK(display_list_);
56 SnapshotPixelFormat snapshot_pixel_format;
57 // This must be kept in sync with painting.dart.
58 switch (target_format) {
59 case 0:
60 snapshot_pixel_format = SnapshotPixelFormat::kDontCare;
61 break;
62 case 1:
63 snapshot_pixel_format = SnapshotPixelFormat::kRGBA32Float;
64 break;
65 case 2:
66 snapshot_pixel_format = SnapshotPixelFormat::kR32Float;
67 break;
68 default:
69 FML_DCHECK(false) << "unknown target format: " << target_format;
70 snapshot_pixel_format = SnapshotPixelFormat::kDontCare;
71 break;
72 }
73 RasterizeToImageSync(display_list_, width, height, snapshot_pixel_format,
74 raw_image_handle);
75}
76
77static sk_sp<DlImage> CreateDeferredImage(
78 bool impeller,
79 sk_sp<DisplayList> display_list,
80 uint32_t width,
81 uint32_t height,
82 SnapshotPixelFormat target_format,
84 fml::RefPtr<fml::TaskRunner> raster_task_runner,
85 const fml::RefPtr<SkiaUnrefQueue>& unref_queue) {
86#if IMPELLER_SUPPORTS_RENDERING
87 if (impeller) {
89 std::move(display_list), DlISize(width, height), target_format,
90 std::move(snapshot_delegate), std::move(raster_task_runner));
91 }
92#endif // IMPELLER_SUPPORTS_RENDERING
93
94#if SLIMPELLER
95 FML_LOG(FATAL) << "Impeller opt-out unavailable.";
96 return nullptr;
97#else // SLIMPELLER
98 const SkImageInfo image_info = SkImageInfo::Make(
99 width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
100 return DlDeferredImageGPUSkia::Make(image_info, std::move(display_list),
101 std::move(snapshot_delegate),
102 raster_task_runner, unref_queue);
103#endif // !SLIMPELLER
104}
105
106// static
107void Picture::RasterizeToImageSync(sk_sp<DisplayList> display_list,
108 uint32_t width,
109 uint32_t height,
110 SnapshotPixelFormat target_format,
111 Dart_Handle raw_image_handle) {
112 auto* dart_state = UIDartState::Current();
113 if (!dart_state) {
114 return;
115 }
116 auto unref_queue = dart_state->GetSkiaUnrefQueue();
117 auto snapshot_delegate = dart_state->GetSnapshotDelegate();
118 auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
119
120 auto image = CanvasImage::Create();
121 auto dl_image = CreateDeferredImage(
122 dart_state->IsImpellerEnabled(), std::move(display_list), width, height,
123 target_format, std::move(snapshot_delegate),
124 std::move(raster_task_runner), unref_queue);
125 image->set_image(dl_image);
126 image->AssociateWithDartWrapper(raw_image_handle);
127}
128
130 display_list_.reset();
132}
133
135 if (display_list_) {
136 return display_list_->bytes() + sizeof(Picture);
137 } else {
138 return sizeof(Picture);
139 }
140}
141
142Dart_Handle Picture::RasterizeToImage(const sk_sp<DisplayList>& display_list,
143 uint32_t width,
144 uint32_t height,
145 Dart_Handle raw_image_callback) {
147 raw_image_callback);
148}
149
151 std::unique_ptr<LayerTree> layer_tree,
152 Dart_Handle raw_image_callback) {
153 FML_DCHECK(layer_tree != nullptr);
154 auto frame_size = layer_tree->frame_size();
155 return DoRasterizeToImage(nullptr, std::move(layer_tree), frame_size.width,
156 frame_size.height, raw_image_callback);
157}
158
159Dart_Handle Picture::DoRasterizeToImage(const sk_sp<DisplayList>& display_list,
160 std::unique_ptr<LayerTree> layer_tree,
161 uint32_t width,
162 uint32_t height,
163 Dart_Handle raw_image_callback) {
164 // Either display_list or layer_tree should be provided.
165 FML_DCHECK((display_list == nullptr) != (layer_tree == nullptr));
166
167 if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) {
168 return tonic::ToDart("Image callback was invalid");
169 }
170
171 if (width == 0 || height == 0) {
172 return tonic::ToDart("Image dimensions for scene were invalid.");
173 }
174
175 auto* dart_state = UIDartState::Current();
176 auto image_callback = std::make_unique<tonic::DartPersistentValue>(
177 dart_state, raw_image_callback);
178 auto unref_queue = dart_state->GetSkiaUnrefQueue();
179 auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
180 auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
181 auto snapshot_delegate = dart_state->GetSnapshotDelegate();
182
183 // We can't create an image on this task runner because we don't have a
184 // graphics context. Even if we did, it would be slow anyway. Also, this
185 // thread owns the sole reference to the layer tree. So we do it in the
186 // raster thread.
187
188 auto ui_task =
189 // The static leak checker gets confused by the use of fml::MakeCopyable.
190 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
191 fml::MakeCopyable([image_callback = std::move(image_callback),
192 unref_queue](sk_sp<DlImage> image) mutable {
193 auto dart_state = image_callback->dart_state().lock();
194 if (!dart_state) {
195 // The root isolate could have died in the meantime.
196 return;
197 }
198 tonic::DartState::Scope scope(dart_state);
199
200 if (!image) {
201 tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
202 return;
203 }
204
205 if (!image->isUIThreadSafe()) {
206 // All images with impeller textures should already be safe.
207 FML_DCHECK(image->impeller_texture() == nullptr);
208 image =
209 DlImageGPU::Make({image->skia_image(), std::move(unref_queue)});
210 }
211
212 auto dart_image = CanvasImage::Create();
213 dart_image->set_image(image);
214 auto* raw_dart_image = tonic::ToDart(dart_image);
215
216 // All done!
217 tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
218
219 // image_callback is associated with the Dart isolate and must be
220 // deleted on the UI thread.
221 image_callback.reset();
222 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
223 });
224
225 // Kick things off on the raster rask runner.
227 raster_task_runner,
228 fml::MakeCopyable([ui_task_runner, snapshot_delegate, display_list, width,
229 height, ui_task,
230 layer_tree = std::move(layer_tree)]() mutable {
231 auto picture_bounds = DlISize(width, height);
232 sk_sp<DisplayList> snapshot_display_list = display_list;
233 if (layer_tree) {
234 FML_DCHECK(picture_bounds == layer_tree->frame_size());
235 snapshot_display_list =
236 layer_tree->Flatten(DlRect::MakeWH(width, height),
237 snapshot_delegate->GetTextureRegistry(),
238 snapshot_delegate->GetGrContext());
239 }
240 snapshot_delegate->MakeRasterSnapshot(
241 snapshot_display_list, picture_bounds,
242 [ui_task_runner, ui_task](const sk_sp<DlImage>& image) {
244 ui_task_runner, [ui_task, image]() { ui_task(image); });
245 },
247 }));
248
249 return Dart_Null();
250 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
251}
252
253} // namespace flutter
static fml::RefPtr< CanvasImage > Create()
Definition image.h:36
static sk_sp< DlDeferredImageGPUImpeller > Make(std::unique_ptr< LayerTree > layer_tree, fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate, fml::RefPtr< fml::TaskRunner > raster_task_runner)
static sk_sp< DlDeferredImageGPUSkia > Make(const SkImageInfo &image_info, sk_sp< DisplayList > display_list, fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate, const fml::RefPtr< fml::TaskRunner > &raster_task_runner, fml::RefPtr< SkiaUnrefQueue > unref_queue)
static sk_sp< DlImageGPU > Make(SkiaGPUObject< SkImage > image)
~Picture() override
sk_sp< DisplayList > display_list() const
Definition picture.h:28
static void RasterizeToImageSync(sk_sp< DisplayList > display_list, uint32_t width, uint32_t height, SnapshotPixelFormat target_format, Dart_Handle raw_image_handle)
Definition picture.cc:107
static void CreateAndAssociateWithDartWrapper(Dart_Handle dart_handle, sk_sp< DisplayList > display_list)
Definition picture.cc:29
Dart_Handle toImage(uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition picture.cc:42
void toImageSync(uint32_t width, uint32_t height, int32_t target_format, Dart_Handle raw_image_handle)
Definition picture.cc:51
static Dart_Handle RasterizeLayerTreeToImage(std::unique_ptr< LayerTree > layer_tree, Dart_Handle raw_image_callback)
Definition picture.cc:150
size_t GetAllocationSize() const
Definition picture.cc:134
static Dart_Handle DoRasterizeToImage(const sk_sp< DisplayList > &display_list, std::unique_ptr< LayerTree > layer_tree, uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition picture.cc:159
static Dart_Handle RasterizeToImage(const sk_sp< DisplayList > &display_list, uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition picture.cc:142
static UIDartState * Current()
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
FlutterVulkanImage * image
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
impeller::ISize32 DlISize
static sk_sp< DlImage > CreateDeferredImage(bool impeller, std::unique_ptr< LayerTree > layer_tree, fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate, fml::RefPtr< fml::TaskRunner > raster_task_runner, const fml::RefPtr< SkiaUnrefQueue > &unref_queue)
Definition scene.cc:74
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition ref_ptr.h:261
Dart_Handle ToDart(const T &object)
Dart_Handle DartInvoke(Dart_Handle closure, std::initializer_list< Dart_Handle > args)
int32_t height
int32_t width
static constexpr TRect MakeWH(Type width, Type height)
Definition rect.h:140