141 {
142
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
150 {
152
153 for (const auto& layer : frame_layers_) {
154 if (!layer.second.canvas_spy->DidDrawIntoCanvas()) {
155 continue;
156 }
157
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() << ")";
168 continue;
169 }
170
171
172
173 if (
surface->GetImageId() == 0) {
174 auto image_id = flatland_->NextContentId().value;
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
184 surface->SetReleaseImageCallback([flatland = flatland_, image_id]() {
185 flatland->flatland()->ReleaseImage({image_id});
186 });
187 }
188
189
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
200 {
202
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);
209 }
210 }
211
212
213 {
215
216
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);
224
225
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
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;
241
242
243 const ViewMutators view_mutators =
244 ParseMutatorStack(view_params.mutatorsStack());
246
247
248
249
250 SkMatrix 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)) {
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 {
277 << "Failed to create viewport because width or height is zero.";
278 }
279 }
280
281
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
294 if (view_mutators.clips != viewport.mutators.clips) {
295
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
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
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
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
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
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();
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.";
391 }
392 }
393
394
395 if (surface_for_layer != nullptr) {
396
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
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
413
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
420
421 {
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
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
450 layer_index++;
451 }
452
453
454
455
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
464 {
466
467 flatland_->Present();
468 }
469
470
471 {
473
474 for (const auto& surface_index : frame_surface_indices) {
476
477 FML_CHECK(surface_index.second < frame_surfaces.size());
478 SurfaceProducerSurface*
surface =
479 frame_surfaces[surface_index.second].get();
481
482 sk_sp<SkSurface> sk_surface =
surface->GetSkiaSurface();
484 FML_CHECK(SkISize::Make(sk_surface->width(), sk_surface->height()) ==
485 frame_size_);
486 SkCanvas* canvas = sk_surface->getCanvas();
488
489 const auto& layer = frame_layers_.find(surface_index.first);
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
503 {
505
506 surface_producer_->SubmitSurfaces(std::move(frame_surfaces));
507 }
508
509
510 frame->Submit();
511}
#define FML_DLOG(severity)
#define FML_DCHECK(condition)
constexpr int64_t kFlutterImplicitViewId
const SkSize & ToSkSize(const DlSize &size)
SkMatrix ToSkMatrix(const DlMatrix &matrix)