Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
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()});
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)));
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()},
414 layer_index == 0 ? fuchsia::ui::composition::BlendMode::SRC
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()) {
619 mutators.opacity *= std::clamp(mutator->GetAlphaFloat(), 0.f, 1.f);
620 } break;
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;
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)
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
void clear(SkColor color)
Definition SkCanvas.h:1199
void setMatrix(const SkM44 &matrix)
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
static const SkMatrix & I()
SkMatrix & preConcat(const SkMatrix &other)
Definition SkMatrix.cpp:674
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:37
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
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
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition p3.cpp:47
static SkRect inset(const SkRect &r)
int32_t width
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
SkScalar fHeight
Definition SkSize.h:54
SkScalar fWidth
Definition SkSize.h:53
#define ERROR(message)
#define TRACE_EVENT0(category_group, name)