138 int64_t flutter_view_id,
140 const std::shared_ptr<impeller::AiksContext>& aiks_context,
141 std::unique_ptr<flutter::SurfaceFrame>
frame) {
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;
153 for (
const auto& layer : frame_layers_) {
154 if (!layer.second.canvas_spy->DidDrawIntoCanvas()) {
159 surface_producer_->ProduceSurface(layer.second.surface_size);
161 const std::string layer_id_str =
162 layer.first.has_value() ? std::to_string(layer.first.value())
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() <<
")";
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));
184 surface->SetReleaseImageCallback([flatland = flatland_, image_id]() {
185 flatland->flatland()->ReleaseImage({image_id});
190 flatland_->EnqueueAcquireFence(
surface->GetAcquireFence());
191 flatland_->EnqueueReleaseFence(
surface->GetReleaseFence());
193 frame_surface_indices.emplace(
194 std::make_pair(layer.first, frame_surfaces.size()));
195 frame_surfaces.emplace_back(std::move(
surface));
203 for (
const auto& surface_index : frame_surface_indices) {
204 const auto& layer = frame_layers_.find(surface_index.first);
206 layer->second.picture =
207 layer->second.recorder->finishRecordingAsPicture();
208 FML_CHECK(layer->second.picture !=
nullptr);
217 const float inv_dpr = 1.0f / frame_dpr_;
218 flatland_->flatland()->SetScale(root_transform_id_, {inv_dpr, inv_dpr});
220 size_t layer_index = 0;
221 for (
const auto& layer_id : frame_composition_order_) {
222 const auto& layer = frame_layers_.find(layer_id);
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();
231 auto found = views_.find(layer_id.value());
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;
243 const ViewMutators view_mutators =
244 ParseMutatorStack(view_params.mutatorsStack());
245 const SkSize view_size = view_params.sizePoints();
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);
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.";
267 if (viewport.pending_create_viewport_callback) {
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;
275 <<
"Failed to create viewport because width or height is zero.";
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;
292 if (view_mutators.clips != viewport.mutators.clips) {
294 while (viewport.clip_transforms.size() < view_mutators.clips.size()) {
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));
300 FML_CHECK(viewport.clip_transforms.size() >=
301 view_mutators.clips.size());
304 for (
auto& clip_transform : viewport.clip_transforms) {
305 DetachClipTransformChildren(flatland_.get(), &clip_transform);
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;
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()});
319 fuchsia::math::Rect rect = {
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)));
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]),
336 viewport.mutators.clips = view_mutators.clips;
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;
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;
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);
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();
383 const std::string layer_id_str =
384 layer_id.has_value() ? std::to_string(layer_id.value())
386 FML_LOG(
ERROR) <<
"Missing surface for layer " << layer_id_str
387 <<
"; skipping scene graph add of layer.";
393 if (surface_for_layer !=
nullptr) {
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));
403 flatland_->flatland()->SetContent(layers_[layer_index].transform_id,
405 flatland_->flatland()->SetImageDestinationSize(
407 {
static_cast<uint32_t
>(surface_for_layer->
GetSize().
width()),
408 static_cast<uint32_t
>(surface_for_layer->
GetSize().
height())});
412 flatland_->flatland()->SetImageBlendingFunction(
414 layer_index == 0 ? fuchsia::ui::composition::BlendMode::SRC
415 : fuchsia::ui::composition::BlendMode::SRC_OVER);
421 std::list<SkRect> intersection_rects =
422 layer->second.rtree->searchNonOverlappingDrawnRects(
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;
437 flatland_->flatland()->SetHitRegions(
438 layers_[layer_index].transform_id, std::move(hit_regions));
442 flatland_->flatland()->AddChild(root_transform_id_,
443 layers_[layer_index].transform_id);
444 child_transforms_.emplace_back(layers_[layer_index].transform_id);
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_);
465 flatland_->Present();
472 for (
const auto& surface_index : frame_surface_indices) {
475 FML_CHECK(surface_index.second < frame_surfaces.size());
477 frame_surfaces[surface_index.second].get();
484 SkCanvas* canvas = sk_surface->getCanvas();
487 const auto& layer = frame_layers_.find(surface_index.first);
495 direct_context->flushAndSubmit();
504 surface_producer_->SubmitSurfaces(std::move(frame_surfaces));