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
17#endif // IMPELLER_SUPPORTS_RENDERING
25
26namespace flutter {
27
29
31 Dart_Handle dart_handle,
32 sk_sp<DisplayList> display_list) {
33 FML_DCHECK(display_list->isUIThreadSafe());
34 auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(display_list));
35 canvas_picture->AssociateWithDartWrapper(dart_handle);
36}
37
38Picture::Picture(sk_sp<DisplayList> display_list)
39 : display_list_(std::move(display_list)) {}
40
41Picture::~Picture() = default;
42
43Dart_Handle Picture::toImage(uint32_t width,
44 uint32_t height,
45 Dart_Handle raw_image_callback) {
46 if (!display_list_) {
47 return tonic::ToDart("Picture is null");
48 }
49 return RasterizeToImage(display_list_, width, height, raw_image_callback);
50}
51
53 uint32_t height,
54 int32_t target_format,
55 Dart_Handle raw_image_handle) {
56 FML_DCHECK(display_list_);
57 SnapshotPixelFormat snapshot_pixel_format;
58 // This must be kept in sync with painting.dart.
59 switch (target_format) {
60 case 0:
61 snapshot_pixel_format = SnapshotPixelFormat::kDontCare;
62 break;
63 case 1:
64 snapshot_pixel_format = SnapshotPixelFormat::kRGBA32Float;
65 break;
66 case 2:
67 snapshot_pixel_format = SnapshotPixelFormat::kR32Float;
68 break;
69 default:
70 FML_DCHECK(false) << "unknown target format: " << target_format;
71 snapshot_pixel_format = SnapshotPixelFormat::kDontCare;
72 break;
73 }
74 RasterizeToImageSync(display_list_, width, height, snapshot_pixel_format,
75 raw_image_handle);
76}
77
78static sk_sp<DlImage> CreateDeferredImage(
79 bool impeller,
80 sk_sp<DisplayList> display_list,
81 uint32_t width,
82 uint32_t height,
83 SnapshotPixelFormat target_format,
85 fml::RefPtr<fml::TaskRunner> raster_task_runner,
86 const fml::RefPtr<SkiaUnrefQueue>& unref_queue) {
87#if IMPELLER_SUPPORTS_RENDERING
88 if (impeller) {
90 std::move(display_list), DlISize(width, height), target_format,
91 std::move(snapshot_delegate), std::move(raster_task_runner));
92 }
93#endif // IMPELLER_SUPPORTS_RENDERING
94
95#if SLIMPELLER
96 FML_LOG(FATAL) << "Impeller opt-out unavailable.";
97 return nullptr;
98#else // SLIMPELLER
99 const SkImageInfo image_info = SkImageInfo::Make(
100 width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
101 return DlDeferredImageGPUSkia::Make(image_info, std::move(display_list),
102 std::move(snapshot_delegate),
103 raster_task_runner, unref_queue);
104#endif // !SLIMPELLER
105}
106
107// static
108void Picture::RasterizeToImageSync(sk_sp<DisplayList> display_list,
109 uint32_t width,
110 uint32_t height,
111 SnapshotPixelFormat target_format,
112 Dart_Handle raw_image_handle) {
113 auto* dart_state = UIDartState::Current();
114 if (!dart_state) {
115 return;
116 }
117 auto unref_queue = dart_state->GetSkiaUnrefQueue();
118 auto snapshot_delegate = dart_state->GetSnapshotDelegate();
119 auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
120
121 auto image = CanvasImage::Create();
122 auto dl_image = CreateDeferredImage(
123 dart_state->IsImpellerEnabled(), std::move(display_list), width, height,
124 target_format, std::move(snapshot_delegate),
125 std::move(raster_task_runner), unref_queue);
126 image->set_image(dl_image);
127 image->AssociateWithDartWrapper(raw_image_handle);
128}
129
131 display_list_.reset();
133}
134
136 if (display_list_) {
137 return display_list_->bytes() + sizeof(Picture);
138 } else {
139 return sizeof(Picture);
140 }
141}
142
143#if IMPELLER_SUPPORTS_RENDERING
144static sk_sp<DlImage> MakeImpellerImage(
145 const std::shared_ptr<impeller::Texture>& texture) {
146 if (texture) {
149 }
150 return nullptr;
151}
152#endif // IMPELLER_SUPPORTS_RENDERING
153
154Dart_Handle Picture::RasterizeToImage(const sk_sp<DisplayList>& display_list,
155 uint32_t width,
156 uint32_t height,
157 Dart_Handle raw_image_callback) {
159 raw_image_callback);
160}
161
163 std::unique_ptr<LayerTree> layer_tree,
164 Dart_Handle raw_image_callback) {
165 FML_DCHECK(layer_tree != nullptr);
166 auto frame_size = layer_tree->frame_size();
167 return DoRasterizeToImage(nullptr, std::move(layer_tree), frame_size.width,
168 frame_size.height, raw_image_callback);
169}
170
171Dart_Handle Picture::DoRasterizeToImage(const sk_sp<DisplayList>& display_list,
172 std::unique_ptr<LayerTree> layer_tree,
173 uint32_t width,
174 uint32_t height,
175 Dart_Handle raw_image_callback) {
176 // Either display_list or layer_tree should be provided.
177 FML_DCHECK((display_list == nullptr) != (layer_tree == nullptr));
178
179 if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) {
180 return tonic::ToDart("Image callback was invalid");
181 }
182
183 if (width == 0 || height == 0) {
184 return tonic::ToDart("Image dimensions for scene were invalid.");
185 }
186
187 auto* dart_state = UIDartState::Current();
188 auto image_callback = std::make_unique<tonic::DartPersistentValue>(
189 dart_state, raw_image_callback);
190 auto unref_queue = dart_state->GetSkiaUnrefQueue();
191 auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
192 auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
193 auto snapshot_delegate = dart_state->GetSnapshotDelegate();
194#if IMPELLER_SUPPORTS_RENDERING
195 auto is_impeller_enabled = dart_state->IsImpellerEnabled();
196#else
197 auto is_impeller_enabled = false;
198#endif // IMPELLER_SUPPORTS_RENDERING
199
200 // We can't create an image on this task runner because we don't have a
201 // graphics context. Even if we did, it would be slow anyway. Also, this
202 // thread owns the sole reference to the layer tree. So we do it in the
203 // raster thread.
204
205 auto ui_task =
206 // The static leak checker gets confused by the use of fml::MakeCopyable.
207 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
208 fml::MakeCopyable([image_callback = std::move(image_callback),
209 unref_queue](sk_sp<DlImage> image) mutable {
210 auto dart_state = image_callback->dart_state().lock();
211 if (!dart_state) {
212 // The root isolate could have died in the meantime.
213 return;
214 }
215 tonic::DartState::Scope scope(dart_state);
216
217 if (!image) {
218 tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
219 return;
220 }
221
222 if (!image->isUIThreadSafe()) {
223 // All images with impeller textures should already be safe.
224 FML_DCHECK(image->GetImageType() == DlImage::Type::kSkia);
225 auto skia_image = image->asSkiaImage();
226 image =
227 DlImageGPU::Make({skia_image ? skia_image->skia_image() : nullptr,
228 std::move(unref_queue)});
229 }
230
231 auto dart_image = CanvasImage::Create();
232 dart_image->set_image(image);
233 auto* raw_dart_image = tonic::ToDart(dart_image);
234
235 // All done!
236 tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
237
238 // image_callback is associated with the Dart isolate and must be
239 // deleted on the UI thread.
240 image_callback.reset();
241 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
242 });
243
244 // Kick things off on the raster rask runner.
246 raster_task_runner,
247 fml::MakeCopyable([ui_task_runner, snapshot_delegate, display_list, width,
248 height, ui_task, is_impeller_enabled,
249 layer_tree = std::move(layer_tree)]() mutable {
250 auto picture_bounds = DlISize(width, height);
251 sk_sp<DisplayList> snapshot_display_list = display_list;
252 if (layer_tree) {
253 FML_DCHECK(picture_bounds == layer_tree->frame_size());
254 snapshot_display_list =
255 layer_tree->Flatten(DlRect::MakeWH(width, height),
256 snapshot_delegate->GetTextureRegistry(),
257 snapshot_delegate->GetGrContext());
258 }
259 if (is_impeller_enabled) {
260#if IMPELLER_SUPPORTS_RENDERING
261 snapshot_delegate->MakeImpellerSnapshot(
262 snapshot_display_list, picture_bounds,
263 [ui_task_runner,
264 ui_task](const std::shared_ptr<impeller::Texture>& texture) {
266 ui_task_runner, [ui_task, texture]() {
267 ui_task(MakeImpellerImage(texture));
268 });
269 },
271#endif // IMPELLER_SUPPORTS_RENDERING
272 } else {
273 snapshot_delegate->MakeSkiaSnapshot(
274 snapshot_display_list, picture_bounds,
275 [ui_task_runner, ui_task](const sk_sp<SkImage>& sk_image) {
277 ui_task_runner, [ui_task, sk_image]() {
278 sk_sp<DlImage> image;
279 if (sk_image) {
280 image = DlImageSkia::Make(sk_image);
281 }
282 ui_task(std::move(image));
283 });
284 },
286 }
287 }));
288
289 return Dart_Null();
290 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
291}
292
293} // 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)
static sk_sp< DlImage > Make(const 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:108
static void CreateAndAssociateWithDartWrapper(Dart_Handle dart_handle, sk_sp< DisplayList > display_list)
Definition picture.cc:30
Dart_Handle toImage(uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition picture.cc:43
void toImageSync(uint32_t width, uint32_t height, int32_t target_format, Dart_Handle raw_image_handle)
Definition picture.cc:52
static Dart_Handle RasterizeLayerTreeToImage(std::unique_ptr< LayerTree > layer_tree, Dart_Handle raw_image_callback)
Definition picture.cc:162
size_t GetAllocationSize() const
Definition picture.cc:135
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:171
static Dart_Handle RasterizeToImage(const sk_sp< DisplayList > &display_list, uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition picture.cc:154
static UIDartState * Current()
static void RunNowOrPostTask(const fml::RefPtr< fml::TaskRunner > &runner, const fml::closure &task)
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
FlutterVulkanImage * image
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
FlTexture * texture
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