Flutter Engine
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 
5 #include "flutter/lib/ui/painting/picture.h"
6 
7 #include <memory>
8 
9 #include "flutter/fml/make_copyable.h"
10 #include "flutter/lib/ui/painting/canvas.h"
11 #include "flutter/lib/ui/ui_dart_state.h"
12 #include "third_party/skia/include/core/SkImage.h"
19 
20 namespace flutter {
21 
23 
24 #define FOR_EACH_BINDING(V) \
25  V(Picture, toImage) \
26  V(Picture, dispose) \
27  V(Picture, GetAllocationSize)
28 
30 
31 fml::RefPtr<Picture> Picture::Create(
32  Dart_Handle dart_handle,
33  flutter::SkiaGPUObject<SkPicture> picture) {
34  auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(picture));
35 
36  canvas_picture->AssociateWithDartWrapper(dart_handle);
37  return canvas_picture;
38 }
39 
41  Dart_Handle dart_handle,
43  auto canvas_picture = fml::MakeRefCounted<Picture>(std::move(display_list));
44 
45  canvas_picture->AssociateWithDartWrapper(dart_handle);
46  return canvas_picture;
47 }
48 
50  : picture_(std::move(picture)) {}
51 
53  : display_list_(std::move(display_list)) {}
54 
55 Picture::~Picture() = default;
56 
57 Dart_Handle Picture::toImage(uint32_t width,
58  uint32_t height,
59  Dart_Handle raw_image_callback) {
60  if (display_list_.skia_object()) {
61  return RasterizeToImage(
62  [display_list = display_list_.skia_object()](SkCanvas* canvas) {
63  display_list->RenderTo(canvas);
64  },
65  width, height, raw_image_callback);
66  } else {
67  if (!picture_.skia_object()) {
68  return tonic::ToDart("Picture is null");
69  }
70  return RasterizeToImage(picture_.skia_object(), width, height,
71  raw_image_callback);
72  }
73 }
74 
76  picture_.reset();
77  display_list_.reset();
79 }
80 
82  if (auto picture = picture_.skia_object()) {
83  return picture->approximateBytesUsed() + sizeof(Picture);
84  } else if (auto display_list = display_list_.skia_object()) {
85  return display_list->bytes() + sizeof(Picture);
86  } else {
87  return sizeof(Picture);
88  }
89 }
90 
91 Dart_Handle Picture::RasterizeToImage(sk_sp<SkPicture> picture,
92  uint32_t width,
93  uint32_t height,
94  Dart_Handle raw_image_callback) {
95  return RasterizeToImage(
96  [picture](SkCanvas* canvas) { canvas->drawPicture(picture); }, width,
97  height, raw_image_callback);
98 }
99 
101  std::function<void(SkCanvas*)> draw_callback,
102  uint32_t width,
103  uint32_t height,
104  Dart_Handle raw_image_callback) {
105  if (Dart_IsNull(raw_image_callback) || !Dart_IsClosure(raw_image_callback)) {
106  return tonic::ToDart("Image callback was invalid");
107  }
108 
109  if (width == 0 || height == 0) {
110  return tonic::ToDart("Image dimensions for scene were invalid.");
111  }
112 
113  auto* dart_state = UIDartState::Current();
114  auto image_callback = std::make_unique<tonic::DartPersistentValue>(
115  dart_state, raw_image_callback);
116  auto unref_queue = dart_state->GetSkiaUnrefQueue();
117  auto ui_task_runner = dart_state->GetTaskRunners().GetUITaskRunner();
118  auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner();
119  auto snapshot_delegate = dart_state->GetSnapshotDelegate();
120 
121  // We can't create an image on this task runner because we don't have a
122  // graphics context. Even if we did, it would be slow anyway. Also, this
123  // thread owns the sole reference to the layer tree. So we flatten the layer
124  // tree into a picture and use that as the thread transport mechanism.
125 
126  auto picture_bounds = SkISize::Make(width, height);
127 
128  auto ui_task = fml::MakeCopyable([image_callback = std::move(image_callback),
129  unref_queue](
130  sk_sp<SkImage> raster_image) mutable {
131  auto dart_state = image_callback->dart_state().lock();
132  if (!dart_state) {
133  // The root isolate could have died in the meantime.
134  return;
135  }
136  tonic::DartState::Scope scope(dart_state);
137 
138  if (!raster_image) {
139  tonic::DartInvoke(image_callback->Get(), {Dart_Null()});
140  return;
141  }
142 
143  auto dart_image = CanvasImage::Create();
144  dart_image->set_image({std::move(raster_image), std::move(unref_queue)});
145  auto* raw_dart_image = tonic::ToDart(std::move(dart_image));
146 
147  // All done!
148  tonic::DartInvoke(image_callback->Get(), {raw_dart_image});
149 
150  // image_callback is associated with the Dart isolate and must be deleted
151  // on the UI thread.
152  image_callback.reset();
153  });
154 
155  // Kick things off on the raster rask runner.
157  raster_task_runner, [ui_task_runner, snapshot_delegate, draw_callback,
158  picture_bounds, ui_task] {
159  sk_sp<SkImage> raster_image = snapshot_delegate->MakeRasterSnapshot(
160  draw_callback, picture_bounds);
161 
163  ui_task_runner,
164  [ui_task, raster_image]() { ui_task(raster_image); });
165  });
166 
167  return Dart_Null();
168 }
169 
170 } // namespace flutter
~Picture() override
#define DART_BIND_ALL(CLASS, FOR_EACH)
static void RunNowOrPostTask(fml::RefPtr< fml::TaskRunner > runner, const fml::closure &task)
Definition: task_runner.cc:55
Dart_NativeFunction function
Definition: fuchsia.cc:51
sk_sp< SkPicture > picture() const
Definition: picture.h:34
sk_sp< DisplayList > display_list() const
Definition: picture.h:35
Dart_Handle DartInvoke(Dart_Handle closure, std::initializer_list< Dart_Handle > args)
Definition: dart_invoke.cc:20
size_t GetAllocationSize() const override
Definition: picture.cc:81
Definition: ascii_trie.cc:9
void dispose()
Definition: picture.cc:75
static fml::RefPtr< Picture > Create(Dart_Handle dart_handle, flutter::SkiaGPUObject< SkPicture > picture)
Definition: picture.cc:31
static fml::RefPtr< CanvasImage > Create()
Definition: image.h:25
internal::CopyableLambda< T > MakeCopyable(T lambda)
Definition: make_copyable.h:57
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
void AssociateWithDartWrapper(Dart_Handle wrappable)
sk_sp< SkiaObjectType > skia_object() const
int32_t width
int32_t height
#define FOR_EACH_BINDING(V)
Definition: picture.cc:24
Dart_Handle ToDart(const T &object)
Dart_Handle toImage(uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition: picture.cc:57
static UIDartState * Current()
static Dart_Handle RasterizeToImage(sk_sp< SkPicture > picture, uint32_t width, uint32_t height, Dart_Handle raw_image_callback)
Definition: picture.cc:91