Flutter Engine
 
Loading...
Searching...
No Matches
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 (flutter::DlISize 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 void CollectView (int64_t view_id)
 
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 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< DlImageFilter > &filter, const DlRect &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}
G_BEGIN_DECLS FlutterViewId view_id
#define FML_CHECK(condition)
Definition logging.h:104

References FML_CHECK, and view_id.

◆ CreateView()

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

Definition at line 513 of file external_view_embedder.cc.

515 {
516 FML_CHECK(views_.find(view_id) == views_.end());
517
518 const auto transform_id = flatland_->NextTransformId();
519 const auto viewport_id = flatland_->NextContentId();
520 View new_view = {.transform_id = transform_id, .viewport_id = viewport_id};
521 flatland_->flatland()->CreateTransform(new_view.transform_id);
522 fuchsia::ui::composition::ChildViewWatcherHandle child_view_watcher;
523 new_view.pending_create_viewport_callback =
524 [this, transform_id, viewport_id, view_id,
525 child_view_watcher_request = child_view_watcher.NewRequest()](
526 const SkSize& size, const SkRect& inset) mutable {
527 fuchsia::ui::composition::ViewportProperties properties;
528 properties.set_logical_size({static_cast<uint32_t>(size.fWidth),
529 static_cast<uint32_t>(size.fHeight)});
530 properties.set_inset({static_cast<int32_t>(inset.fTop),
531 static_cast<int32_t>(inset.fRight),
532 static_cast<int32_t>(inset.fBottom),
533 static_cast<int32_t>(inset.fLeft)});
534 flatland_->flatland()->CreateViewport(
535 viewport_id, {zx::channel((zx_handle_t)view_id)},
536 std::move(properties), std::move(child_view_watcher_request));
537 flatland_->flatland()->SetContent(transform_id, viewport_id);
538 };
539
540 on_view_created();
541 on_view_bound(new_view.viewport_id, std::move(child_view_watcher));
542 views_.emplace(std::make_pair(view_id, std::move(new_view)));
543}
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all 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

References FML_CHECK, and view_id.

◆ DestroyView()

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

Definition at line 545 of file external_view_embedder.cc.

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

References FML_CHECK, view, and view_id.

◆ 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)

References TRACE_EVENT0.

◆ 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:101

References FML_LOG.

◆ 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.

References flutter::kSuccess.

◆ PrepareFlutterView()

void flutter_runner::ExternalViewEmbedder::PrepareFlutterView ( flutter::DlISize  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_ = flutter::ToSkISize(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}
const SkISize & ToSkISize(const DlISize &size)

References flutter::ToSkISize().

◆ 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

References FML_CHECK, params, and view_id.

◆ SetViewProperties()

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

Definition at line 580 of file external_view_embedder.cc.

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

References FML_CHECK, and view_id.

◆ 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 
)
override

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 = flutter::ToSkSize(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 SkMatrix view_params_transformMatrix =
251 flutter::ToSkMatrix(view_params.transformMatrix());
252 for (int index = 0; index < 9; index++) {
253 const SkScalar mutators_transform_value =
254 view_mutators.total_transform.get(index);
255 const SkScalar params_transform_value =
256 view_params_transformMatrix.get(index);
257 if (!SkScalarNearlyEqual(mutators_transform_value,
258 params_transform_value, 0.0005f)) {
259 FML_LOG(ERROR)
260 << "Assertion failed: view_mutators.total_transform[" << index
261 << "] (" << mutators_transform_value
262 << ") != view_params_transformMatrix[" << index << "] ("
263 << params_transform_value
264 << "). This likely means there is a bug with the "
265 << "logic for parsing embedded views' transform matrices.";
266 }
267 }
268
269 if (viewport.pending_create_viewport_callback) {
270 if (view_size.fWidth && view_size.fHeight) {
271 viewport.pending_create_viewport_callback(
272 view_size, viewport.pending_occlusion_hint);
273 viewport.size = view_size;
274 viewport.occlusion_hint = viewport.pending_occlusion_hint;
275 } else {
276 FML_DLOG(WARNING)
277 << "Failed to create viewport because width or height is zero.";
278 }
279 }
280
281 // Set transform for the viewport.
282 if (view_mutators.transform != viewport.mutators.transform) {
283 flatland_->flatland()->SetTranslation(
284 viewport.transform_id,
285 {static_cast<int32_t>(view_mutators.transform.getTranslateX()),
286 static_cast<int32_t>(view_mutators.transform.getTranslateY())});
287 flatland_->flatland()->SetScale(
288 viewport.transform_id, {view_mutators.transform.getScaleX(),
289 view_mutators.transform.getScaleY()});
290 viewport.mutators.transform = view_mutators.transform;
291 }
292
293 // Set clip regions.
294 if (view_mutators.clips != viewport.mutators.clips) {
295 // Expand the clip_transforms array to fit any new transforms.
296 while (viewport.clip_transforms.size() < view_mutators.clips.size()) {
297 ClipTransform clip_transform;
298 clip_transform.transform_id = flatland_->NextTransformId();
299 flatland_->flatland()->CreateTransform(clip_transform.transform_id);
300 viewport.clip_transforms.emplace_back(std::move(clip_transform));
301 }
302 FML_CHECK(viewport.clip_transforms.size() >=
303 view_mutators.clips.size());
304
305 // Adjust and re-parent all clip transforms.
306 for (auto& clip_transform : viewport.clip_transforms) {
307 DetachClipTransformChildren(flatland_.get(), &clip_transform);
308 }
309
310 for (size_t c = 0; c < view_mutators.clips.size(); c++) {
311 const SkMatrix& clip_matrix = view_mutators.clips[c].transform;
312 const SkRect& clip_rect = view_mutators.clips[c].rect;
313
314 flatland_->flatland()->SetTranslation(
315 viewport.clip_transforms[c].transform_id,
316 {static_cast<int32_t>(clip_matrix.getTranslateX()),
317 static_cast<int32_t>(clip_matrix.getTranslateY())});
318 flatland_->flatland()->SetScale(
319 viewport.clip_transforms[c].transform_id,
320 {clip_matrix.getScaleX(), clip_matrix.getScaleY()});
321 fuchsia::math::Rect rect = {
322 static_cast<int32_t>(clip_rect.x()),
323 static_cast<int32_t>(clip_rect.y()),
324 static_cast<int32_t>(clip_rect.width()),
325 static_cast<int32_t>(clip_rect.height())};
326 flatland_->flatland()->SetClipBoundary(
327 viewport.clip_transforms[c].transform_id,
328 std::make_unique<fuchsia::math::Rect>(std::move(rect)));
329
330 const auto child_transform_id =
331 c != (view_mutators.clips.size() - 1)
332 ? viewport.clip_transforms[c + 1].transform_id
333 : viewport.transform_id;
334 AttachClipTransformChild(flatland_.get(),
335 &(viewport.clip_transforms[c]),
336 child_transform_id);
337 }
338 viewport.mutators.clips = view_mutators.clips;
339 }
340
341 // Set opacity.
342 if (view_mutators.opacity != viewport.mutators.opacity) {
343 flatland_->flatland()->SetOpacity(viewport.transform_id,
344 view_mutators.opacity);
345 viewport.mutators.opacity = view_mutators.opacity;
346 }
347
348 // Set size and occlusion hint.
349 if (view_size != viewport.size ||
350 viewport.pending_occlusion_hint != viewport.occlusion_hint) {
351 fuchsia::ui::composition::ViewportProperties properties;
352 properties.set_logical_size(
353 {static_cast<uint32_t>(view_size.fWidth),
354 static_cast<uint32_t>(view_size.fHeight)});
355 properties.set_inset(
356 {static_cast<int32_t>(viewport.pending_occlusion_hint.fTop),
357 static_cast<int32_t>(viewport.pending_occlusion_hint.fRight),
358 static_cast<int32_t>(viewport.pending_occlusion_hint.fBottom),
359 static_cast<int32_t>(viewport.pending_occlusion_hint.fLeft)});
360 flatland_->flatland()->SetViewportProperties(viewport.viewport_id,
361 std::move(properties));
362 viewport.size = view_size;
363 viewport.occlusion_hint = viewport.pending_occlusion_hint;
364 }
365
366 // Attach the View to the main scene graph.
367 const auto main_child_transform =
368 viewport.mutators.clips.empty()
369 ? viewport.transform_id
370 : viewport.clip_transforms[0].transform_id;
371 flatland_->flatland()->AddChild(root_transform_id_,
372 main_child_transform);
373 child_transforms_.emplace_back(main_child_transform);
374 }
375
376 // Acquire the surface associated with the layer.
377 SurfaceProducerSurface* surface_for_layer = nullptr;
378 if (layer->second.canvas_spy->DidDrawIntoCanvas()) {
379 const auto& surface_index = frame_surface_indices.find(layer_id);
380 if (surface_index != frame_surface_indices.end()) {
381 FML_CHECK(surface_index->second < frame_surfaces.size());
382 surface_for_layer = frame_surfaces[surface_index->second].get();
383 FML_CHECK(surface_for_layer != nullptr);
384 } else {
385 const std::string layer_id_str =
386 layer_id.has_value() ? std::to_string(layer_id.value())
387 : "Background";
388 FML_LOG(ERROR) << "Missing surface for layer " << layer_id_str
389 << "; skipping scene graph add of layer.";
390 FML_DCHECK(false);
391 }
392 }
393
394 // Draw the layer if we acquired a surface for it successfully.
395 if (surface_for_layer != nullptr) {
396 // Create a new layer if needed for the surface.
397 FML_CHECK(layer_index <= layers_.size());
398 if (layer_index == layers_.size()) {
399 Layer new_layer{.transform_id = flatland_->NextTransformId()};
400 flatland_->flatland()->CreateTransform(new_layer.transform_id);
401 layers_.emplace_back(std::move(new_layer));
402 }
403
404 // Update the image content and set size.
405 flatland_->flatland()->SetContent(layers_[layer_index].transform_id,
406 {surface_for_layer->GetImageId()});
407 flatland_->flatland()->SetImageDestinationSize(
408 {surface_for_layer->GetImageId()},
409 {static_cast<uint32_t>(surface_for_layer->GetSize().width()),
410 static_cast<uint32_t>(surface_for_layer->GetSize().height())});
411
412 // Flutter Embedder lacks an API to detect if a layer has alpha or not.
413 // For now, we assume any layer beyond the first has alpha.
414 flatland_->flatland()->SetImageBlendingFunction(
415 {surface_for_layer->GetImageId()},
416 layer_index == 0 ? fuchsia::ui::composition::BlendMode::SRC
417 : fuchsia::ui::composition::BlendMode::SRC_OVER);
418
419 // Set hit regions for this layer; these hit regions correspond to the
420 // portions of the layer on which skia drew content.
421 {
422 FML_CHECK(layer->second.rtree);
423 std::list<SkRect> intersection_rects =
424 layer->second.rtree->searchNonOverlappingDrawnRects(
425 SkRect::Make(layer->second.surface_size));
426
427 std::vector<fuchsia::ui::composition::HitRegion> hit_regions;
428 for (const SkRect& rect : intersection_rects) {
429 hit_regions.emplace_back();
430 auto& new_hit_region = hit_regions.back();
431 new_hit_region.region.x = rect.x();
432 new_hit_region.region.y = rect.y();
433 new_hit_region.region.width = rect.width();
434 new_hit_region.region.height = rect.height();
435 new_hit_region.hit_test =
436 fuchsia::ui::composition::HitTestInteraction::DEFAULT;
437 }
438
439 flatland_->flatland()->SetHitRegions(
440 layers_[layer_index].transform_id, std::move(hit_regions));
441 }
442
443 // Attach the Layer to the main scene graph.
444 flatland_->flatland()->AddChild(root_transform_id_,
445 layers_[layer_index].transform_id);
446 child_transforms_.emplace_back(layers_[layer_index].transform_id);
447 }
448
449 // Reset for the next pass:
450 layer_index++;
451 }
452
453 // Set up the input interceptor at the top of the scene, if applicable. It
454 // will capture all input, and any unwanted input will be reinjected into
455 // embedded views.
456 if (input_interceptor_transform_.has_value()) {
457 flatland_->flatland()->AddChild(root_transform_id_,
458 *input_interceptor_transform_);
459 child_transforms_.emplace_back(*input_interceptor_transform_);
460 }
461 }
462
463 // Present the session to Scenic, along with surface acquire/release fences.
464 {
465 TRACE_EVENT0("flutter", "SessionPresent");
466
467 flatland_->Present();
468 }
469
470 // Render the recorded SkPictures into the surfaces.
471 {
472 TRACE_EVENT0("flutter", "RasterizeSurfaces");
473
474 for (const auto& surface_index : frame_surface_indices) {
475 TRACE_EVENT0("flutter", "RasterizeSurface");
476
477 FML_CHECK(surface_index.second < frame_surfaces.size());
478 SurfaceProducerSurface* surface =
479 frame_surfaces[surface_index.second].get();
480 FML_CHECK(surface != nullptr);
481
482 sk_sp<SkSurface> sk_surface = surface->GetSkiaSurface();
483 FML_CHECK(sk_surface != nullptr);
484 FML_CHECK(SkISize::Make(sk_surface->width(), sk_surface->height()) ==
485 frame_size_);
486 SkCanvas* canvas = sk_surface->getCanvas();
487 FML_CHECK(canvas != nullptr);
488
489 const auto& layer = frame_layers_.find(surface_index.first);
490 FML_CHECK(layer != frame_layers_.end());
491
492 canvas->setMatrix(SkMatrix::I());
493 canvas->clear(SK_ColorTRANSPARENT);
494 canvas->drawPicture(layer->second.picture);
495 if (GrDirectContext* direct_context =
496 GrAsDirectContext(canvas->recordingContext())) {
497 direct_context->flushAndSubmit();
498 }
499 }
500 }
501
502 // Flush deferred Skia work and inform Scenic that render targets are ready.
503 {
504 TRACE_EVENT0("flutter", "PresentSurfaces");
505
506 surface_producer_->SubmitSurfaces(std::move(frame_surfaces));
507 }
508
509 // Submit the underlying render-backend-specific frame for processing.
510 frame->Submit();
511}
VkSurfaceKHR surface
Definition main.cc:65
#define FML_DLOG(severity)
Definition logging.h:121
#define FML_DCHECK(condition)
Definition logging.h:122
constexpr int64_t kFlutterImplicitViewId
Definition constants.h:35
const SkSize & ToSkSize(const DlSize &size)
SkMatrix ToSkMatrix(const DlMatrix &matrix)
int32_t width

References FML_CHECK, FML_DCHECK, FML_DLOG, FML_LOG, flutter_runner::SurfaceProducerSurface::GetImageId(), flutter_runner::SurfaceProducerSurface::GetSize(), flutter::kFlutterImplicitViewId, surface, flutter::ToSkMatrix(), flutter::ToSkSize(), TRACE_EVENT0, flutter_runner::ExternalViewEmbedder::ClipTransform::transform_id, and width.

◆ 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: