1010
1111#include < algorithm> // For std::clamp
1212
13- #include " flutter/fml/logging.h"
1413#include " flutter/fml/trace_event.h"
1514#include " third_party/skia/include/core/SkPicture.h"
1615#include " third_party/skia/include/core/SkSurface.h"
@@ -170,9 +169,8 @@ void GfxExternalViewEmbedder::PrerollCompositeEmbeddedView(
170169 zx_handle_t handle = static_cast <zx_handle_t >(view_id);
171170 FML_CHECK (frame_layers_.count (handle) == 0 );
172171
173- frame_layers_.emplace (std::make_pair (
174- EmbedderLayerId{handle},
175- EmbedderLayer (frame_size_, *params, flutter::RTreeFactory ())));
172+ frame_layers_.emplace (std::make_pair (EmbedderLayerId{handle},
173+ EmbedderLayer (frame_size_, *params)));
176174 frame_composition_order_.push_back (handle);
177175}
178176
@@ -202,9 +200,8 @@ void GfxExternalViewEmbedder::BeginFrame(
202200 frame_dpr_ = device_pixel_ratio;
203201
204202 // Create the root layer.
205- frame_layers_.emplace (std::make_pair (
206- kRootLayerId ,
207- EmbedderLayer (frame_size, std::nullopt , flutter::RTreeFactory ())));
203+ frame_layers_.emplace (
204+ std::make_pair (kRootLayerId , EmbedderLayer (frame_size, std::nullopt )));
208205 frame_composition_order_.push_back (kRootLayerId );
209206
210207 // Set up the input interceptor at the top of the scene, if applicable.
@@ -274,19 +271,6 @@ void GfxExternalViewEmbedder::SubmitFrame(
274271 }
275272 }
276273
277- // Finish recording SkPictures.
278- {
279- TRACE_EVENT0 (" flutter" , " FinishRecordingPictures" );
280-
281- for (const auto & surface_index : frame_surface_indices) {
282- const auto & layer = frame_layers_.find (surface_index.first );
283- FML_CHECK (layer != frame_layers_.end ());
284- layer->second .picture =
285- layer->second .recorder ->finishRecordingAsPicture ();
286- FML_CHECK (layer->second .picture != nullptr );
287- }
288- }
289-
290274 // Submit layers and platform views to Scenic in composition order.
291275 {
292276 TRACE_EVENT0 (" flutter" , " SubmitLayers" );
@@ -453,18 +437,10 @@ void GfxExternalViewEmbedder::SubmitFrame(
453437 FML_CHECK (scenic_layer_index <= scenic_layers_.size ());
454438 if (scenic_layer_index == scenic_layers_.size ()) {
455439 ScenicLayer new_layer{
456- .layer_node = scenic::EntityNode (session_->get ()),
457- .image =
458- ScenicImage{
459- .shape_node = scenic::ShapeNode (session_->get ()),
460- .material = scenic::Material (session_->get ()),
461- },
462- // We'll set hit regions later.
463- .hit_regions = {},
440+ .shape_node = scenic::ShapeNode (session_->get ()),
441+ .material = scenic::Material (session_->get ()),
464442 };
465- new_layer.layer_node .SetLabel (" Flutter::Layer" );
466- new_layer.layer_node .AddChild (new_layer.image .shape_node );
467- new_layer.image .shape_node .SetMaterial (new_layer.image .material );
443+ new_layer.shape_node .SetMaterial (new_layer.material );
468444 scenic_layers_.emplace_back (std::move (new_layer));
469445 }
470446
@@ -515,50 +491,25 @@ void GfxExternalViewEmbedder::SubmitFrame(
515491 embedded_views_height;
516492 auto & scenic_layer = scenic_layers_[scenic_layer_index];
517493 auto & scenic_rect = found_rects->second [rect_index];
518- auto & image = scenic_layer.image ;
519- image.shape_node .SetLabel (" Flutter::Layer::Image" );
520- image.shape_node .SetShape (scenic_rect);
521- image.shape_node .SetTranslation (
494+ scenic_layer.shape_node .SetLabel (" Flutter::Layer" );
495+ scenic_layer.shape_node .SetShape (scenic_rect);
496+ scenic_layer.shape_node .SetTranslation (
522497 layer->second .surface_size .width () * 0 .5f ,
523498 layer->second .surface_size .height () * 0 .5f , -layer_elevation);
524- image.material .SetColor (SK_AlphaOPAQUE, SK_AlphaOPAQUE, SK_AlphaOPAQUE,
525- layer_opacity);
526- image.material .SetTexture (surface_for_layer->GetImageId ());
527-
528- // We'll set hit regions expliclty on a separate ShapeNode, so the image
529- // itself should be unhittable and semantically invisible.
530- image.shape_node .SetHitTestBehavior (
531- fuchsia::ui::gfx::HitTestBehavior::kSuppress );
532- image.shape_node .SetSemanticVisibility (false );
499+ scenic_layer.material .SetColor (SK_AlphaOPAQUE, SK_AlphaOPAQUE,
500+ SK_AlphaOPAQUE, layer_opacity);
501+ scenic_layer.material .SetTexture (surface_for_layer->GetImageId ());
502+
503+ // Only the first (i.e. the bottom-most) layer should receive input.
504+ // TODO: Workaround for invisible overlays stealing input. Remove when
505+ // the underlying bug is fixed.
506+ const fuchsia::ui::gfx::HitTestBehavior layer_hit_test_behavior =
507+ first_layer ? fuchsia::ui::gfx::HitTestBehavior::kDefault
508+ : fuchsia::ui::gfx::HitTestBehavior::kSuppress ;
509+ scenic_layer.shape_node .SetHitTestBehavior (layer_hit_test_behavior);
533510
534511 // Attach the ScenicLayer to the main scene graph.
535- layer_tree_node_.AddChild (scenic_layer.layer_node );
536-
537- // Compute the set of non-overlapping set of bounding boxes for the
538- // painted content in this layer.
539- {
540- FML_CHECK (layer->second .rtree );
541- std::list<SkRect> intersection_rects =
542- layer->second .rtree ->searchNonOverlappingDrawnRects (
543- SkRect::Make (layer->second .surface_size ));
544-
545- // SkRect joined_rect = SkRect::MakeEmpty();
546- for (const SkRect& rect : intersection_rects) {
547- auto paint_bounds =
548- scenic::Rectangle (session_->get (), rect.width (), rect.height ());
549- auto hit_region = scenic::ShapeNode (session_->get ());
550- hit_region.SetLabel (" Flutter::Layer::HitRegion" );
551- hit_region.SetShape (paint_bounds);
552- hit_region.SetTranslation (rect.centerX (), rect.centerY (),
553- -layer_elevation);
554- hit_region.SetHitTestBehavior (
555- fuchsia::ui::gfx::HitTestBehavior::kDefault );
556- hit_region.SetSemanticVisibility (true );
557-
558- scenic_layer.layer_node .AddChild (hit_region);
559- scenic_layer.hit_regions .push_back (std::move (hit_region));
560- }
561- }
512+ layer_tree_node_.AddChild (scenic_layer.shape_node );
562513 }
563514
564515 // Reset for the next pass:
@@ -576,11 +527,7 @@ void GfxExternalViewEmbedder::SubmitFrame(
576527 session_->Present ();
577528 }
578529
579- // Flush pending skia operations.
580- // NOTE: This operation MUST occur AFTER the `Present() ` call above. We
581- // pipeline the Skia rendering work with scenic IPC, and scenic will delay
582- // internally until Skia is finished. So, doing this work before calling
583- // `Present()` would adversely affect performance.
530+ // Render the recorded SkPictures into the surfaces.
584531 {
585532 TRACE_EVENT0 (" flutter" , " RasterizeSurfaces" );
586533
@@ -601,10 +548,13 @@ void GfxExternalViewEmbedder::SubmitFrame(
601548
602549 const auto & layer = frame_layers_.find (surface_index.first );
603550 FML_CHECK (layer != frame_layers_.end ());
551+ sk_sp<SkPicture> picture =
552+ layer->second .recorder ->finishRecordingAsPicture ();
553+ FML_CHECK (picture != nullptr );
604554
605555 canvas->setMatrix (SkMatrix::I ());
606556 canvas->clear (SK_ColorTRANSPARENT);
607- canvas->drawPicture (layer-> second . picture );
557+ canvas->drawPicture (picture);
608558 canvas->flush ();
609559 }
610560 }
@@ -686,16 +636,7 @@ void GfxExternalViewEmbedder::Reset() {
686636
687637 // Clear images on all layers so they aren't cached unnecessarily.
688638 for (auto & layer : scenic_layers_) {
689- layer.image .material .SetTexture (0 );
690-
691- // Detach hit regions; otherwise, they may persist across frames
692- // incorrectly.
693- for (auto & hit_region : layer.hit_regions ) {
694- hit_region.Detach ();
695- }
696-
697- // Remove cached hit regions so that we don't recreate stale ones.
698- layer.hit_regions .clear ();
639+ layer.material .SetTexture (0 );
699640 }
700641}
701642
0 commit comments