Flutter Engine
The Flutter Engine
external_view_embedder.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
6
7#include <algorithm>
8#include <cstdint>
9
10#include "flutter/common/constants.h"
11#include "flutter/fml/trace_event.h"
16
17namespace flutter_runner {
18namespace {
19
20void AttachClipTransformChild(
21 FlatlandConnection* flatland,
22 ExternalViewEmbedder::ClipTransform* parent_clip_transform,
23 const fuchsia::ui::composition::TransformId& child_transform_id) {
24 flatland->flatland()->AddChild(parent_clip_transform->transform_id,
25 child_transform_id);
26 parent_clip_transform->children.push_back(child_transform_id);
27}
28
29void DetachClipTransformChildren(
30 FlatlandConnection* flatland,
31 ExternalViewEmbedder::ClipTransform* clip_transform) {
32 for (auto& child : clip_transform->children) {
33 flatland->flatland()->RemoveChild(clip_transform->transform_id, child);
34 }
35 clip_transform->children.clear();
36}
37
38} // namespace
39
41 fuchsia::ui::views::ViewCreationToken view_creation_token,
42 fuchsia::ui::views::ViewIdentityOnCreation view_identity,
43 fuchsia::ui::composition::ViewBoundProtocols view_protocols,
44 fidl::InterfaceRequest<fuchsia::ui::composition::ParentViewportWatcher>
45 parent_viewport_watcher_request,
46 std::shared_ptr<FlatlandConnection> flatland,
47 std::shared_ptr<SurfaceProducer> surface_producer,
48 bool intercept_all_input)
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}
70
72
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}
85
87 int64_t view_id,
88 std::unique_ptr<flutter::EmbeddedViewParams> params) {
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}
97
99 int64_t view_id) {
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}
106
108 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
110}
111
113 GrDirectContext* context,
114 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
115
116// |ExternalViewEmbedder|
118 double device_pixel_ratio) {
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}
130
132 bool should_resubmit_frame,
133 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
134 TRACE_EVENT0("flutter", "ExternalViewEmbedder::EndFrame");
135}
136
138 int64_t flutter_view_id,
139 GrDirectContext* context,
140 const std::shared_ptr<impeller::AiksContext>& aiks_context,
141 std::unique_ptr<flutter::SurfaceFrame> frame) {
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());
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}
510
512 ViewCallback on_view_created,
513 ViewCreatedCallback on_view_bound) {
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}
542
544 ViewIdCallback on_view_unbound) {
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}
577
579 const SkRect& occlusion_hint,
580 bool hit_testable,
581 bool focusable) {
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}
590
591void ExternalViewEmbedder::Reset() {
592 frame_layers_.clear();
593 frame_composition_order_.clear();
594 frame_size_ = SkISize::Make(0, 0);
595 frame_dpr_ = 1.f;
596
597 // Clear all children from root.
598 for (const auto& transform : child_transforms_) {
599 flatland_->flatland()->RemoveChild(root_transform_id_, transform);
600 }
601 child_transforms_.clear();
602
603 // Clear images on all layers so they aren't cached unnecessarily.
604 for (const auto& layer : layers_) {
605 flatland_->flatland()->SetContent(layer.transform_id, {0});
606 }
607}
608
609ExternalViewEmbedder::ViewMutators ExternalViewEmbedder::ParseMutatorStack(
610 const flutter::MutatorsStack& mutators_stack) {
611 ViewMutators mutators;
612 SkMatrix total_transform = SkMatrix::I();
613 SkMatrix transform_accumulator = SkMatrix::I();
614
615 for (auto i = mutators_stack.Begin(); i != mutators_stack.End(); ++i) {
616 const auto& mutator = *i;
617 switch (mutator->GetType()) {
618 case flutter::MutatorType::kOpacity: {
619 mutators.opacity *= std::clamp(mutator->GetAlphaFloat(), 0.f, 1.f);
620 } break;
621 case flutter::MutatorType::kTransform: {
622 total_transform.preConcat(mutator->GetMatrix());
623 transform_accumulator.preConcat(mutator->GetMatrix());
624 } break;
626 mutators.clips.emplace_back(TransformedClip{
627 .transform = transform_accumulator,
628 .rect = mutator->GetRect(),
629 });
630 transform_accumulator = SkMatrix::I();
631 } break;
633 mutators.clips.emplace_back(TransformedClip{
634 .transform = transform_accumulator,
635 .rect = mutator->GetRRect().getBounds(),
636 });
637 transform_accumulator = SkMatrix::I();
638 } break;
639 case flutter::MutatorType::kClipPath: {
640 mutators.clips.emplace_back(TransformedClip{
641 .transform = transform_accumulator,
642 .rect = mutator->GetPath().getBounds(),
643 });
644 transform_accumulator = SkMatrix::I();
645 } break;
646 default: {
647 break;
648 }
649 }
650 }
651 mutators.total_transform = total_transform;
652 mutators.transform = transform_accumulator;
653 mutators.opacity = std::clamp(mutators.opacity, 0.f, 1.f);
654
655 return mutators;
656}
657
658} // namespace flutter_runner
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
static unsigned clamp(SkFixed fx, int max)
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
SkMatrix & preConcat(const SkMatrix &other)
Definition: SkMatrix.cpp:674
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
int width() const
Definition: SkSurface.h:178
int height() const
Definition: SkSurface.h:184
Developer-facing API for rendering anything within the engine.
Definition: dl_canvas.h:38
const std::vector< std::shared_ptr< Mutator > >::const_iterator End() const
const std::vector< std::shared_ptr< Mutator > >::const_iterator Begin() const
void EndFrame(bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
flutter::PostPrerollResult PostPrerollAction(const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
void PrepareFlutterView(SkISize frame_size, double device_pixel_ratio) override
void DestroyView(int64_t view_id, ViewIdCallback on_view_unbound)
void CreateView(int64_t view_id, ViewCallback on_view_created, ViewCreatedCallback on_view_bound)
flutter::DlCanvas * CompositeEmbeddedView(int64_t view_id) override
flutter::DlCanvas * GetRootCanvas() 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 BeginFrame(GrDirectContext *context, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger) override
void SetViewProperties(int64_t view_id, const SkRect &occlusion_hint, bool hit_testable, bool focusable)
void PrerollCompositeEmbeddedView(int64_t view_id, std::unique_ptr< flutter::EmbeddedViewParams > params) override
virtual SkISize GetSize() const =0
const EmbeddedViewParams * params
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_LOG(severity)
Definition: logging.h:82
#define FML_CHECK(condition)
Definition: logging.h:85
#define FML_DCHECK(condition)
Definition: logging.h:103
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
std::function< void()> ViewCallback
std::function< void(fuchsia::ui::composition::ContentId)> ViewIdCallback
std::function< void(fuchsia::ui::composition::ContentId, fuchsia::ui::composition::ChildViewWatcherHandle child_view_watcher)> ViewCreatedCallback
constexpr int64_t kFlutterImplicitViewId
Definition: constants.h:35
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
TRect< Scalar > Rect
Definition: rect.h:769
static SkString to_string(int n)
Definition: nanobench.cpp:119
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
static SkRect inset(const SkRect &r)
int32_t width
Definition: SkSize.h:16
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
constexpr int32_t height() const
Definition: SkSize.h:37
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
constexpr float x() const
Definition: SkRect.h:720
constexpr float y() const
Definition: SkRect.h:727
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
Definition: SkSize.h:52
SkScalar fHeight
Definition: SkSize.h:54
SkScalar fWidth
Definition: SkSize.h:53
fuchsia::ui::composition::TransformId transform_id
#define ERROR(message)
Definition: elf_loader.cc:260
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131