Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Attributes | List of all members
flutter_runner::ExternalViewEmbedder Class Referencefinal

#include <external_view_embedder.h>

Inheritance diagram for flutter_runner::ExternalViewEmbedder:
flutter::ExternalViewEmbedder

Classes

struct  ClipTransform
 

Public Member Functions

 ExternalViewEmbedder (fuchsia::ui::views::ViewCreationToken view_creation_token, fuchsia::ui::views::ViewIdentityOnCreation view_identity, fuchsia::ui::composition::ViewBoundProtocols endpoints, fidl::InterfaceRequest< fuchsia::ui::composition::ParentViewportWatcher > parent_viewport_watcher_request, std::shared_ptr< FlatlandConnection > flatland, std::shared_ptr< SurfaceProducer > surface_producer, bool intercept_all_input=false)
 
 ~ExternalViewEmbedder ()
 
flutter::DlCanvasGetRootCanvas () override
 
void PrerollCompositeEmbeddedView (int64_t view_id, std::unique_ptr< flutter::EmbeddedViewParams > params) override
 
flutter::DlCanvasCompositeEmbeddedView (int64_t view_id) override
 
flutter::PostPrerollResult PostPrerollAction (const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
 
void BeginFrame (GrDirectContext *context, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
 
void PrepareFlutterView (SkISize frame_size, double device_pixel_ratio) override
 
void EndFrame (bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
 
void SubmitFlutterView (int64_t flutter_view_id, GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, std::unique_ptr< flutter::SurfaceFrame > frame) override
 
void CancelFrame () override
 
bool SupportsDynamicThreadMerging () override
 
void CreateView (int64_t view_id, ViewCallback on_view_created, ViewCreatedCallback on_view_bound)
 
void DestroyView (int64_t view_id, ViewIdCallback on_view_unbound)
 
void SetViewProperties (int64_t view_id, const SkRect &occlusion_hint, bool hit_testable, bool focusable)
 
- Public Member Functions inherited from flutter::ExternalViewEmbedder
 ExternalViewEmbedder ()=default
 
virtual ~ExternalViewEmbedder ()=default
 
virtual void CollectView (int64_t view_id)
 
virtual DlCanvasGetRootCanvas ()=0
 
virtual void CancelFrame ()=0
 
virtual void BeginFrame (GrDirectContext *context, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)=0
 
virtual void PrerollCompositeEmbeddedView (int64_t platform_view_id, std::unique_ptr< EmbeddedViewParams > params)=0
 
virtual PostPrerollResult PostPrerollAction (const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)
 
virtual DlCanvasCompositeEmbeddedView (int64_t platform_view_id)=0
 
virtual void PrepareFlutterView (SkISize frame_size, double device_pixel_ratio)=0
 
virtual void SubmitFlutterView (int64_t flutter_view_id, GrDirectContext *context, const std::shared_ptr< impeller::AiksContext > &aiks_context, std::unique_ptr< SurfaceFrame > frame)
 
virtual void EndFrame (bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger)
 
virtual bool SupportsDynamicThreadMerging ()
 
virtual void Teardown ()
 
void SetUsedThisFrame (bool used_this_frame)
 
bool GetUsedThisFrame () const
 
virtual void PushVisitedPlatformView (int64_t platform_view_id)
 
virtual void PushFilterToVisitedPlatformViews (const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
 

Static Public Attributes

static constexpr uint32_t kDefaultViewportSize = 32
 

Detailed Description

Definition at line 43 of file external_view_embedder.h.

Constructor & Destructor Documentation

◆ ExternalViewEmbedder()

flutter_runner::ExternalViewEmbedder::ExternalViewEmbedder ( fuchsia::ui::views::ViewCreationToken  view_creation_token,
fuchsia::ui::views::ViewIdentityOnCreation  view_identity,
fuchsia::ui::composition::ViewBoundProtocols  endpoints,
fidl::InterfaceRequest< fuchsia::ui::composition::ParentViewportWatcher >  parent_viewport_watcher_request,
std::shared_ptr< FlatlandConnection flatland,
std::shared_ptr< SurfaceProducer surface_producer,
bool  intercept_all_input = false 
)

Definition at line 40 of file external_view_embedder.cc.

49 : flatland_(flatland), surface_producer_(surface_producer) {
50 flatland_->flatland()->CreateView2(
51 std::move(view_creation_token), std::move(view_identity),
52 std::move(view_protocols), std::move(parent_viewport_watcher_request));
53
54 root_transform_id_ = flatland_->NextTransformId();
55 flatland_->flatland()->CreateTransform(root_transform_id_);
56 flatland_->flatland()->SetRootTransform(root_transform_id_);
57
58 if (intercept_all_input) {
59 input_interceptor_transform_ = flatland_->NextTransformId();
60 flatland_->flatland()->CreateTransform(*input_interceptor_transform_);
61 flatland_->flatland()->SetInfiniteHitRegion(
62 *input_interceptor_transform_,
63 fuchsia::ui::composition::HitTestInteraction::SEMANTICALLY_INVISIBLE);
64
65 flatland_->flatland()->AddChild(root_transform_id_,
66 *input_interceptor_transform_);
67 child_transforms_.emplace_back(*input_interceptor_transform_);
68 }
69}

◆ ~ExternalViewEmbedder()

flutter_runner::ExternalViewEmbedder::~ExternalViewEmbedder ( )
virtualdefault

Reimplemented from flutter::ExternalViewEmbedder.

Member Function Documentation

◆ BeginFrame()

void flutter_runner::ExternalViewEmbedder::BeginFrame ( GrDirectContext context,
const fml::RefPtr< fml::RasterThreadMerger > &  raster_thread_merger 
)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 112 of file external_view_embedder.cc.

114 {}

◆ CancelFrame()

void flutter_runner::ExternalViewEmbedder::CancelFrame ( )
inlineoverridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 96 of file external_view_embedder.h.

96{ Reset(); }

◆ CompositeEmbeddedView()

flutter::DlCanvas * flutter_runner::ExternalViewEmbedder::CompositeEmbeddedView ( int64_t  view_id)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 98 of file external_view_embedder.cc.

99 {
100 zx_handle_t handle = static_cast<zx_handle_t>(view_id);
101 auto found = frame_layers_.find(handle);
102 FML_CHECK(found != frame_layers_.end());
103
104 return found->second.canvas_spy->GetSpyingCanvas();
105}
#define FML_CHECK(condition)
Definition: logging.h:85

◆ CreateView()

void flutter_runner::ExternalViewEmbedder::CreateView ( int64_t  view_id,
ViewCallback  on_view_created,
ViewCreatedCallback  on_view_bound 
)

Definition at line 511 of file external_view_embedder.cc.

513 {
514 FML_CHECK(views_.find(view_id) == views_.end());
515
516 const auto transform_id = flatland_->NextTransformId();
517 const auto viewport_id = flatland_->NextContentId();
518 View new_view = {.transform_id = transform_id, .viewport_id = viewport_id};
519 flatland_->flatland()->CreateTransform(new_view.transform_id);
520 fuchsia::ui::composition::ChildViewWatcherHandle child_view_watcher;
521 new_view.pending_create_viewport_callback =
522 [this, transform_id, viewport_id, view_id,
523 child_view_watcher_request = child_view_watcher.NewRequest()](
524 const SkSize& size, const SkRect& inset) mutable {
525 fuchsia::ui::composition::ViewportProperties properties;
526 properties.set_logical_size({static_cast<uint32_t>(size.fWidth),
527 static_cast<uint32_t>(size.fHeight)});
528 properties.set_inset({static_cast<int32_t>(inset.fTop),
529 static_cast<int32_t>(inset.fRight),
530 static_cast<int32_t>(inset.fBottom),
531 static_cast<int32_t>(inset.fLeft)});
532 flatland_->flatland()->CreateViewport(
533 viewport_id, {zx::channel((zx_handle_t)view_id)},
534 std::move(properties), std::move(child_view_watcher_request));
535 flatland_->flatland()->SetContent(transform_id, viewport_id);
536 };
537
538 on_view_created();
539 on_view_bound(new_view.viewport_id, std::move(child_view_watcher));
540 views_.emplace(std::make_pair(view_id, std::move(new_view)));
541}
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
static SkRect inset(const SkRect &r)
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
Definition: SkSize.h:52

◆ DestroyView()

void flutter_runner::ExternalViewEmbedder::DestroyView ( int64_t  view_id,
ViewIdCallback  on_view_unbound 
)

Definition at line 543 of file external_view_embedder.cc.

544 {
545 auto view = views_.find(view_id);
546 FML_CHECK(view != views_.end());
547
548 auto viewport_id = view->second.viewport_id;
549 auto transform_id = view->second.transform_id;
550 auto& clip_transforms = view->second.clip_transforms;
551 if (!view->second.pending_create_viewport_callback) {
552 flatland_->flatland()->ReleaseViewport(viewport_id, [](auto) {});
553 }
554 auto itr = std::find_if(
555 child_transforms_.begin(), child_transforms_.end(),
556 [transform_id,
557 &clip_transforms](fuchsia::ui::composition::TransformId id) {
558 return id.value == transform_id.value ||
559 (!clip_transforms.empty() &&
560 (id.value == clip_transforms[0].transform_id.value));
561 });
562 if (itr != child_transforms_.end()) {
563 flatland_->flatland()->RemoveChild(root_transform_id_, *itr);
564 child_transforms_.erase(itr);
565 }
566 for (auto& clip_transform : clip_transforms) {
567 DetachClipTransformChildren(flatland_.get(), &clip_transform);
568 }
569 flatland_->flatland()->ReleaseTransform(transform_id);
570 for (auto& clip_transform : clip_transforms) {
571 flatland_->flatland()->ReleaseTransform(clip_transform.transform_id);
572 }
573
574 views_.erase(view);
575 on_view_unbound(viewport_id);
576}

◆ EndFrame()

void flutter_runner::ExternalViewEmbedder::EndFrame ( bool  should_resubmit_frame,
const fml::RefPtr< fml::RasterThreadMerger > &  raster_thread_merger 
)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 131 of file external_view_embedder.cc.

133 {
134 TRACE_EVENT0("flutter", "ExternalViewEmbedder::EndFrame");
135}
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131

◆ GetRootCanvas()

flutter::DlCanvas * flutter_runner::ExternalViewEmbedder::GetRootCanvas ( )
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 73 of file external_view_embedder.cc.

73 {
74 auto found = frame_layers_.find(kRootLayerId);
75 if (found == frame_layers_.end()) {
76 FML_LOG(WARNING)
77 << "No root canvas could be found. This is extremely unlikely and "
78 "indicates that the external view embedder did not receive the "
79 "notification to begin the frame.";
80 return nullptr;
81 }
82
83 return found->second.canvas_spy->GetSpyingCanvas();
84}
#define FML_LOG(severity)
Definition: logging.h:82

◆ PostPrerollAction()

flutter::PostPrerollResult flutter_runner::ExternalViewEmbedder::PostPrerollAction ( const fml::RefPtr< fml::RasterThreadMerger > &  raster_thread_merger)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 107 of file external_view_embedder.cc.

◆ PrepareFlutterView()

void flutter_runner::ExternalViewEmbedder::PrepareFlutterView ( SkISize  frame_size,
double  device_pixel_ratio 
)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 117 of file external_view_embedder.cc.

118 {
119 // Reset for new view.
120 Reset();
121 frame_size_ = frame_size;
122 frame_dpr_ = device_pixel_ratio;
123
124 // Create the root layer.
125 frame_layers_.emplace(std::make_pair(
126 kRootLayerId,
127 EmbedderLayer(frame_size, std::nullopt, flutter::RTreeFactory())));
128 frame_composition_order_.push_back(kRootLayerId);
129}

◆ PrerollCompositeEmbeddedView()

void flutter_runner::ExternalViewEmbedder::PrerollCompositeEmbeddedView ( int64_t  view_id,
std::unique_ptr< flutter::EmbeddedViewParams params 
)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 86 of file external_view_embedder.cc.

88 {
89 zx_handle_t handle = static_cast<zx_handle_t>(view_id);
90 FML_CHECK(frame_layers_.count(handle) == 0);
91
92 frame_layers_.emplace(std::make_pair(
93 EmbedderLayerId{handle},
94 EmbedderLayer(frame_size_, *params, flutter::RTreeFactory())));
95 frame_composition_order_.push_back(handle);
96}
const EmbeddedViewParams * params

◆ SetViewProperties()

void flutter_runner::ExternalViewEmbedder::SetViewProperties ( int64_t  view_id,
const SkRect occlusion_hint,
bool  hit_testable,
bool  focusable 
)

Definition at line 578 of file external_view_embedder.cc.

581 {
582 auto found = views_.find(view_id);
583 FML_CHECK(found != views_.end());
584
585 // Note that pending_create_viewport_callback might not have run at this
586 // point.
587 auto& viewport = found->second;
588 viewport.pending_occlusion_hint = occlusion_hint;
589}

◆ SubmitFlutterView()

void flutter_runner::ExternalViewEmbedder::SubmitFlutterView ( int64_t  flutter_view_id,
GrDirectContext context,
const std::shared_ptr< impeller::AiksContext > &  aiks_context,
std::unique_ptr< flutter::SurfaceFrame frame 
)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 137 of file external_view_embedder.cc.

141 {
142 // Fuchsia only supports operating the implicit view for now.
144
145 TRACE_EVENT0("flutter", "ExternalViewEmbedder::SubmitFlutterView");
146 std::vector<std::unique_ptr<SurfaceProducerSurface>> frame_surfaces;
147 std::unordered_map<EmbedderLayerId, size_t> frame_surface_indices;
148
149 // Create surfaces for the frame and associate them with layer IDs.
150 {
151 TRACE_EVENT0("flutter", "CreateSurfaces");
152
153 for (const auto& layer : frame_layers_) {
154 if (!layer.second.canvas_spy->DidDrawIntoCanvas()) {
155 continue;
156 }
157
158 auto surface =
159 surface_producer_->ProduceSurface(layer.second.surface_size);
160 if (!surface) {
161 const std::string layer_id_str =
162 layer.first.has_value() ? std::to_string(layer.first.value())
163 : "Background";
164 FML_LOG(ERROR) << "Failed to create surface for layer " << layer_id_str
165 << "; size (" << layer.second.surface_size.width()
166 << ", " << layer.second.surface_size.height() << ")";
167 FML_DCHECK(false);
168 continue;
169 }
170
171 // If we receive an unitialized surface, we need to first create flatland
172 // resource.
173 if (surface->GetImageId() == 0) {
174 auto image_id = flatland_->NextContentId().value;
175 const auto& size = surface->GetSize();
176 fuchsia::ui::composition::ImageProperties image_properties;
177 image_properties.set_size({static_cast<uint32_t>(size.width()),
178 static_cast<uint32_t>(size.height())});
179 flatland_->flatland()->CreateImage(
180 {image_id}, surface->GetBufferCollectionImportToken(), 0,
181 std::move(image_properties));
182
183 surface->SetImageId(image_id);
184 surface->SetReleaseImageCallback([flatland = flatland_, image_id]() {
185 flatland->flatland()->ReleaseImage({image_id});
186 });
187 }
188
189 // Enqueue fences for the next present.
190 flatland_->EnqueueAcquireFence(surface->GetAcquireFence());
191 flatland_->EnqueueReleaseFence(surface->GetReleaseFence());
192
193 frame_surface_indices.emplace(
194 std::make_pair(layer.first, frame_surfaces.size()));
195 frame_surfaces.emplace_back(std::move(surface));
196 }
197 }
198
199 // Finish recording SkPictures.
200 {
201 TRACE_EVENT0("flutter", "FinishRecordingPictures");
202
203 for (const auto& surface_index : frame_surface_indices) {
204 const auto& layer = frame_layers_.find(surface_index.first);
205 FML_CHECK(layer != frame_layers_.end());
206 layer->second.picture =
207 layer->second.recorder->finishRecordingAsPicture();
208 FML_CHECK(layer->second.picture != nullptr);
209 }
210 }
211
212 // Submit layers and platform views to Scenic in composition order.
213 {
214 TRACE_EVENT0("flutter", "SubmitLayers");
215
216 // First re-scale everything according to the DPR.
217 const float inv_dpr = 1.0f / frame_dpr_;
218 flatland_->flatland()->SetScale(root_transform_id_, {inv_dpr, inv_dpr});
219
220 size_t layer_index = 0;
221 for (const auto& layer_id : frame_composition_order_) {
222 const auto& layer = frame_layers_.find(layer_id);
223 FML_CHECK(layer != frame_layers_.end());
224
225 // Draw the PlatformView associated with each layer first.
226 if (layer_id.has_value()) {
227 FML_CHECK(layer->second.embedded_view_params.has_value());
228 auto& view_params = layer->second.embedded_view_params.value();
229
230 // Get the View structure corresponding to the platform view.
231 auto found = views_.find(layer_id.value());
232 FML_CHECK(found != views_.end())
233 << "No View for layer_id = " << layer_id.value()
234 << ". This typically indicates that the Dart code in "
235 "Fuchsia's fuchsia_scenic_flutter library failed to create "
236 "the platform view, leading to a crash later down the road in "
237 "the Flutter Engine code that tries to find that platform view. "
238 "Check the Flutter Framework for changes to PlatformView that "
239 "might have caused a regression.";
240 auto& viewport = found->second;
241
242 // Compute mutators, and size for the platform view.
243 const ViewMutators view_mutators =
244 ParseMutatorStack(view_params.mutatorsStack());
245 const SkSize view_size = view_params.sizePoints();
246
247 // Verify that we're unpacking the mutators' transform matrix correctly.
248 // Use built-in get method for SkMatrix to get values, see:
249 // https://source.corp.google.com/piper///depot/google3/third_party/skia/HEAD/include/core/SkMatrix.h;l=391
250 for (int index = 0; index < 9; index++) {
251 const SkScalar mutators_transform_value =
252 view_mutators.total_transform.get(index);
253 const SkScalar params_transform_value =
254 view_params.transformMatrix().get(index);
255 if (!SkScalarNearlyEqual(mutators_transform_value,
256 params_transform_value, 0.0005f)) {
258 << "Assertion failed: view_mutators.total_transform[" << index
259 << "] (" << mutators_transform_value
260 << ") != view_params.transformMatrix()[" << index << "] ("
261 << params_transform_value
262 << "). This likely means there is a bug with the "
263 << "logic for parsing embedded views' transform matrices.";
264 }
265 }
266
267 if (viewport.pending_create_viewport_callback) {
268 if (view_size.fWidth && view_size.fHeight) {
269 viewport.pending_create_viewport_callback(
270 view_size, viewport.pending_occlusion_hint);
271 viewport.size = view_size;
272 viewport.occlusion_hint = viewport.pending_occlusion_hint;
273 } else {
274 FML_DLOG(WARNING)
275 << "Failed to create viewport because width or height is zero.";
276 }
277 }
278
279 // Set transform for the viewport.
280 if (view_mutators.transform != viewport.mutators.transform) {
281 flatland_->flatland()->SetTranslation(
282 viewport.transform_id,
283 {static_cast<int32_t>(view_mutators.transform.getTranslateX()),
284 static_cast<int32_t>(view_mutators.transform.getTranslateY())});
285 flatland_->flatland()->SetScale(
286 viewport.transform_id, {view_mutators.transform.getScaleX(),
287 view_mutators.transform.getScaleY()});
288 viewport.mutators.transform = view_mutators.transform;
289 }
290
291 // Set clip regions.
292 if (view_mutators.clips != viewport.mutators.clips) {
293 // Expand the clip_transforms array to fit any new transforms.
294 while (viewport.clip_transforms.size() < view_mutators.clips.size()) {
295 ClipTransform clip_transform;
296 clip_transform.transform_id = flatland_->NextTransformId();
297 flatland_->flatland()->CreateTransform(clip_transform.transform_id);
298 viewport.clip_transforms.emplace_back(std::move(clip_transform));
299 }
300 FML_CHECK(viewport.clip_transforms.size() >=
301 view_mutators.clips.size());
302
303 // Adjust and re-parent all clip transforms.
304 for (auto& clip_transform : viewport.clip_transforms) {
305 DetachClipTransformChildren(flatland_.get(), &clip_transform);
306 }
307
308 for (size_t c = 0; c < view_mutators.clips.size(); c++) {
309 const SkMatrix& clip_matrix = view_mutators.clips[c].transform;
310 const SkRect& clip_rect = view_mutators.clips[c].rect;
311
312 flatland_->flatland()->SetTranslation(
313 viewport.clip_transforms[c].transform_id,
314 {static_cast<int32_t>(clip_matrix.getTranslateX()),
315 static_cast<int32_t>(clip_matrix.getTranslateY())});
316 flatland_->flatland()->SetScale(
317 viewport.clip_transforms[c].transform_id,
318 {clip_matrix.getScaleX(), clip_matrix.getScaleY()});
320 static_cast<int32_t>(clip_rect.x()),
321 static_cast<int32_t>(clip_rect.y()),
322 static_cast<int32_t>(clip_rect.width()),
323 static_cast<int32_t>(clip_rect.height())};
324 flatland_->flatland()->SetClipBoundary(
325 viewport.clip_transforms[c].transform_id,
326 std::make_unique<fuchsia::math::Rect>(std::move(rect)));
327
328 const auto child_transform_id =
329 c != (view_mutators.clips.size() - 1)
330 ? viewport.clip_transforms[c + 1].transform_id
331 : viewport.transform_id;
332 AttachClipTransformChild(flatland_.get(),
333 &(viewport.clip_transforms[c]),
334 child_transform_id);
335 }
336 viewport.mutators.clips = view_mutators.clips;
337 }
338
339 // Set opacity.
340 if (view_mutators.opacity != viewport.mutators.opacity) {
341 flatland_->flatland()->SetOpacity(viewport.transform_id,
342 view_mutators.opacity);
343 viewport.mutators.opacity = view_mutators.opacity;
344 }
345
346 // Set size and occlusion hint.
347 if (view_size != viewport.size ||
348 viewport.pending_occlusion_hint != viewport.occlusion_hint) {
349 fuchsia::ui::composition::ViewportProperties properties;
350 properties.set_logical_size(
351 {static_cast<uint32_t>(view_size.fWidth),
352 static_cast<uint32_t>(view_size.fHeight)});
353 properties.set_inset(
354 {static_cast<int32_t>(viewport.pending_occlusion_hint.fTop),
355 static_cast<int32_t>(viewport.pending_occlusion_hint.fRight),
356 static_cast<int32_t>(viewport.pending_occlusion_hint.fBottom),
357 static_cast<int32_t>(viewport.pending_occlusion_hint.fLeft)});
358 flatland_->flatland()->SetViewportProperties(viewport.viewport_id,
359 std::move(properties));
360 viewport.size = view_size;
361 viewport.occlusion_hint = viewport.pending_occlusion_hint;
362 }
363
364 // Attach the View to the main scene graph.
365 const auto main_child_transform =
366 viewport.mutators.clips.empty()
367 ? viewport.transform_id
368 : viewport.clip_transforms[0].transform_id;
369 flatland_->flatland()->AddChild(root_transform_id_,
370 main_child_transform);
371 child_transforms_.emplace_back(main_child_transform);
372 }
373
374 // Acquire the surface associated with the layer.
375 SurfaceProducerSurface* surface_for_layer = nullptr;
376 if (layer->second.canvas_spy->DidDrawIntoCanvas()) {
377 const auto& surface_index = frame_surface_indices.find(layer_id);
378 if (surface_index != frame_surface_indices.end()) {
379 FML_CHECK(surface_index->second < frame_surfaces.size());
380 surface_for_layer = frame_surfaces[surface_index->second].get();
381 FML_CHECK(surface_for_layer != nullptr);
382 } else {
383 const std::string layer_id_str =
384 layer_id.has_value() ? std::to_string(layer_id.value())
385 : "Background";
386 FML_LOG(ERROR) << "Missing surface for layer " << layer_id_str
387 << "; skipping scene graph add of layer.";
388 FML_DCHECK(false);
389 }
390 }
391
392 // Draw the layer if we acquired a surface for it successfully.
393 if (surface_for_layer != nullptr) {
394 // Create a new layer if needed for the surface.
395 FML_CHECK(layer_index <= layers_.size());
396 if (layer_index == layers_.size()) {
397 Layer new_layer{.transform_id = flatland_->NextTransformId()};
398 flatland_->flatland()->CreateTransform(new_layer.transform_id);
399 layers_.emplace_back(std::move(new_layer));
400 }
401
402 // Update the image content and set size.
403 flatland_->flatland()->SetContent(layers_[layer_index].transform_id,
404 {surface_for_layer->GetImageId()});
405 flatland_->flatland()->SetImageDestinationSize(
406 {surface_for_layer->GetImageId()},
407 {static_cast<uint32_t>(surface_for_layer->GetSize().width()),
408 static_cast<uint32_t>(surface_for_layer->GetSize().height())});
409
410 // Flutter Embedder lacks an API to detect if a layer has alpha or not.
411 // For now, we assume any layer beyond the first has alpha.
412 flatland_->flatland()->SetImageBlendingFunction(
413 {surface_for_layer->GetImageId()},
415 : fuchsia::ui::composition::BlendMode::SRC_OVER);
416
417 // Set hit regions for this layer; these hit regions correspond to the
418 // portions of the layer on which skia drew content.
419 {
420 FML_CHECK(layer->second.rtree);
421 std::list<SkRect> intersection_rects =
422 layer->second.rtree->searchNonOverlappingDrawnRects(
423 SkRect::Make(layer->second.surface_size));
424
425 std::vector<fuchsia::ui::composition::HitRegion> hit_regions;
426 for (const SkRect& rect : intersection_rects) {
427 hit_regions.emplace_back();
428 auto& new_hit_region = hit_regions.back();
429 new_hit_region.region.x = rect.x();
430 new_hit_region.region.y = rect.y();
431 new_hit_region.region.width = rect.width();
432 new_hit_region.region.height = rect.height();
433 new_hit_region.hit_test =
434 fuchsia::ui::composition::HitTestInteraction::DEFAULT;
435 }
436
437 flatland_->flatland()->SetHitRegions(
438 layers_[layer_index].transform_id, std::move(hit_regions));
439 }
440
441 // Attach the Layer to the main scene graph.
442 flatland_->flatland()->AddChild(root_transform_id_,
443 layers_[layer_index].transform_id);
444 child_transforms_.emplace_back(layers_[layer_index].transform_id);
445 }
446
447 // Reset for the next pass:
448 layer_index++;
449 }
450
451 // Set up the input interceptor at the top of the scene, if applicable. It
452 // will capture all input, and any unwanted input will be reinjected into
453 // embedded views.
454 if (input_interceptor_transform_.has_value()) {
455 flatland_->flatland()->AddChild(root_transform_id_,
456 *input_interceptor_transform_);
457 child_transforms_.emplace_back(*input_interceptor_transform_);
458 }
459 }
460
461 // Present the session to Scenic, along with surface acquire/release fences.
462 {
463 TRACE_EVENT0("flutter", "SessionPresent");
464
465 flatland_->Present();
466 }
467
468 // Render the recorded SkPictures into the surfaces.
469 {
470 TRACE_EVENT0("flutter", "RasterizeSurfaces");
471
472 for (const auto& surface_index : frame_surface_indices) {
473 TRACE_EVENT0("flutter", "RasterizeSurface");
474
475 FML_CHECK(surface_index.second < frame_surfaces.size());
476 SurfaceProducerSurface* surface =
477 frame_surfaces[surface_index.second].get();
478 FML_CHECK(surface != nullptr);
479
480 sk_sp<SkSurface> sk_surface = surface->GetSkiaSurface();
481 FML_CHECK(sk_surface != nullptr);
482 FML_CHECK(SkISize::Make(sk_surface->width(), sk_surface->height()) ==
483 frame_size_);
484 SkCanvas* canvas = sk_surface->getCanvas();
485 FML_CHECK(canvas != nullptr);
486
487 const auto& layer = frame_layers_.find(surface_index.first);
488 FML_CHECK(layer != frame_layers_.end());
489
490 canvas->setMatrix(SkMatrix::I());
491 canvas->clear(SK_ColorTRANSPARENT);
492 canvas->drawPicture(layer->second.picture);
493 if (GrDirectContext* direct_context =
495 direct_context->flushAndSubmit();
496 }
497 }
498 }
499
500 // Flush deferred Skia work and inform Scenic that render targets are ready.
501 {
502 TRACE_EVENT0("flutter", "PresentSurfaces");
503
504 surface_producer_->SubmitSurfaces(std::move(frame_surfaces));
505 }
506
507 // Submit the underlying render-backend-specific frame for processing.
508 frame->Submit();
509}
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
void clear(SkColor color)
Definition: SkCanvas.h:1199
void setMatrix(const SkM44 &matrix)
Definition: SkCanvas.cpp:1349
void drawPicture(const SkPicture *picture)
Definition: SkCanvas.h:1961
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
int width() const
Definition: SkSurface.h:178
int height() const
Definition: SkSurface.h:184
VkSurfaceKHR surface
Definition: main.cc:49
double frame
Definition: examples.cpp:31
float SkScalar
Definition: extension.cpp:12
#define FML_DLOG(severity)
Definition: logging.h:102
#define FML_DCHECK(condition)
Definition: logging.h:103
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
constexpr int64_t kFlutterImplicitViewId
Definition: constants.h:35
TRect< Scalar > Rect
Definition: rect.h:769
static SkString to_string(int n)
Definition: nanobench.cpp:119
int32_t width
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
constexpr float x() const
Definition: SkRect.h:720
constexpr float y() const
Definition: SkRect.h:727
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
SkScalar fHeight
Definition: SkSize.h:54
SkScalar fWidth
Definition: SkSize.h:53
#define ERROR(message)
Definition: elf_loader.cc:260

◆ SupportsDynamicThreadMerging()

bool flutter_runner::ExternalViewEmbedder::SupportsDynamicThreadMerging ( )
inlineoverridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 99 of file external_view_embedder.h.

99{ return false; }

Member Data Documentation

◆ kDefaultViewportSize

constexpr uint32_t flutter_runner::ExternalViewEmbedder::kDefaultViewportSize = 32
staticconstexpr

Definition at line 45 of file external_view_embedder.h.


The documentation for this class was generated from the following files: