From 65b7c965f65ae8650ac8607f4bc859d1cdb20578 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Mon, 3 Feb 2020 17:21:22 -0800 Subject: [PATCH] [fuchsia] Avoid creating separate system layers for PhysicalShapeLayers. Change PhysicalShapeLayers to be composited by Flutter by default. In this case, shadows will be rendered too. If there is embedded Fuchsia content in the scene (a ChildSceneLayer), PhysicalShapeLayers that appear above the embedded content will be turned into their own Scenic layers. In this case, there will be no shadows rendered, as it is in the current implementation. We will change this later after clients adjust their usage of PSL once this change lands. --- flow/layers/child_scene_layer.cc | 5 +- flow/layers/layer.h | 5 + flow/layers/layer_tree.cc | 2 +- flow/layers/opacity_layer.cc | 51 +-------- flow/layers/opacity_layer.h | 1 - flow/layers/physical_shape_layer.cc | 105 +++++++++++++----- flow/layers/physical_shape_layer.h | 7 ++ flow/layers/transform_layer.cc | 8 +- flow/scene_update_context.cc | 55 +++++---- flow/scene_update_context.h | 28 ++++- flow/view_holder.cc | 9 +- flow/view_holder.h | 2 + .../platform/fuchsia/flutter/vulkan_surface.h | 4 +- .../fuchsia/flutter/vulkan_surface_pool.h | 2 +- .../fuchsia/flutter/vulkan_surface_producer.h | 2 +- 15 files changed, 170 insertions(+), 116 deletions(-) diff --git a/flow/layers/child_scene_layer.cc b/flow/layers/child_scene_layer.cc index 4a5358053928f..cec30f7b3d05d 100644 --- a/flow/layers/child_scene_layer.cc +++ b/flow/layers/child_scene_layer.cc @@ -20,6 +20,7 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id, void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll"); set_needs_system_composite(true); + context->child_scene_layer_exists_below = true; // An alpha "hole punch" is required if the frame behind us is not opaque. if (!context->is_opaque) { @@ -49,7 +50,9 @@ void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) { auto* view_holder = ViewHolder::FromId(layer_id_); FML_DCHECK(view_holder); - view_holder->UpdateScene(context, offset_, size_, hit_testable_); + view_holder->UpdateScene(context, offset_, size_, + sk_float_round2int(context.alphaf() * 255), + hit_testable_); } } // namespace flutter diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 63c7cdb316d7e..661851d8b8304 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -66,6 +66,11 @@ struct PrerollContext { float total_elevation = 0.0f; bool has_platform_view = false; bool is_opaque = true; +#if defined(OS_FUCHSIA) + // True if, during the traversal so far, we have seen a child_scene_layer. + // Informs whether a layer needs to be system composited. + bool child_scene_layer_exists_below = false; +#endif // defined(OS_FUCHSIA) }; // Represents a single composited layer. Created on the UI thread but then diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 37c28e861bf8a..61560abbed5d4 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -83,7 +83,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context, context, SkRRect::MakeRect( SkRect::MakeWH(frame_size_.width(), frame_size_.height())), - SK_ColorTRANSPARENT, SK_AlphaOPAQUE); + SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::LayerTree"); if (root_layer_->needs_system_composite()) { root_layer_->UpdateScene(context); } diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index e6ca90a66a42f..7899c31784b89 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -9,11 +9,6 @@ namespace flutter { -// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting -// when using the system compositor. Choose a small but non-zero value for -// this. -constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f; - OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset) : alpha_(alpha), offset_(offset) { // Ensure OpacityLayer has only one direct child. @@ -40,8 +35,6 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkMatrix child_matrix = matrix; child_matrix.postTranslate(offset_.fX, offset_.fY); - total_elevation_ = context->total_elevation; - context->total_elevation += kOpacityElevationWhenUsingSystemCompositor; context->is_opaque = parent_is_opaque && (alpha_ == SK_AlphaOPAQUE); context->mutators_stack.PushTransform( SkMatrix::MakeTrans(offset_.fX, offset_.fY)); @@ -52,17 +45,7 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { context->mutators_stack.Pop(); context->mutators_stack.Pop(); context->is_opaque = parent_is_opaque; - context->total_elevation = total_elevation_; -#if defined(OS_FUCHSIA) - if (needs_system_composite()) { - // When using the system compositor, do not include the offset since we - // are rendering as a separate piece of geometry and the offset will be - // baked into that geometry's transform. - frameRRect_ = SkRRect::MakeRect(paint_bounds()); - set_paint_bounds(SkRect::MakeEmpty()); - } else -#endif { set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY)); if (!context->has_platform_view && context->raster_cache && @@ -123,36 +106,10 @@ void OpacityLayer::Paint(PaintContext& context) const { #if defined(OS_FUCHSIA) void OpacityLayer::UpdateScene(SceneUpdateContext& context) { - FML_DCHECK(needs_system_composite()); - TRACE_EVENT0("flutter", "OpacityLayer::UpdateScene"); - - ContainerLayer* container = GetChildContainer(); - FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf. - - SceneUpdateContext::Transform transform( - context, SkMatrix::MakeTrans(offset_.fX, offset_.fY)); - - // Retained rendering: speedup by reusing a retained entity node if possible. - // When an entity node is reused, no paint layer is added to the frame so we - // won't call PhysicalShapeLayer::Paint. - LayerRasterCacheKey key(unique_id(), context.Matrix()); - if (context.HasRetainedNode(key)) { - TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit"); - const scenic::EntityNode& retained_node = context.GetRetainedNode(key); - FML_DCHECK(context.top_entity()); - FML_DCHECK(retained_node.session() == context.session()); - context.top_entity()->embedder_node().AddChild(retained_node); - return; - } - - TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); - // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame( - context, frameRRect_, SK_ColorTRANSPARENT, alpha_, - kOpacityElevationWhenUsingSystemCompositor, total_elevation_, this); - frame.AddPaintLayer(container); - - UpdateSceneChildren(context); + float saved_alpha = context.alphaf(); + context.set_alphaf(context.alphaf() * (alpha_ / 255.f)); + ContainerLayer::UpdateScene(context); + context.set_alphaf(saved_alpha); } #endif // defined(OS_FUCHSIA) diff --git a/flow/layers/opacity_layer.h b/flow/layers/opacity_layer.h index efc5dd4f83e04..658dd1a7b8488 100644 --- a/flow/layers/opacity_layer.h +++ b/flow/layers/opacity_layer.h @@ -43,7 +43,6 @@ class OpacityLayer : public ContainerLayer { SkAlpha alpha_; SkPoint offset_; SkRRect frameRRect_; - float total_elevation_ = 0.0f; FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer); }; diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index c64049222a8e7..af1b6dc14f65b 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -52,23 +52,32 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context, context->total_elevation += elevation_; total_elevation_ = context->total_elevation; +#if defined(OS_FUCHSIA) + child_layer_exists_below_ = context->child_scene_layer_exists_below; + context->child_scene_layer_exists_below = false; + #endif + SkRect child_paint_bounds; PrerollChildren(context, matrix, &child_paint_bounds); + +#if defined(OS_FUCHSIA) + children_need_system_compositing_ = needs_system_composite(); + if (child_layer_exists_below_) { + set_needs_system_composite(true); + } + context->child_scene_layer_exists_below = + context->child_scene_layer_exists_below || child_layer_exists_below_; +#endif context->total_elevation -= elevation_; if (elevation_ == 0) { set_paint_bounds(path_.getBounds()); } else { -#if defined(OS_FUCHSIA) - // Let the system compositor draw all shadows for us. - set_needs_system_composite(true); -#else // We will draw the shadow in Paint(), so add some margin to the paint // bounds to leave space for the shadow. We fill this whole region and clip // children to it so we don't need to join the child paint bounds. set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_, context->frame_device_pixel_ratio)); -#endif // defined(OS_FUCHSIA) } } @@ -78,30 +87,64 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) { FML_DCHECK(needs_system_composite()); TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene"); - // Retained rendering: speedup by reusing a retained entity node if possible. - // When an entity node is reused, no paint layer is added to the frame so we - // won't call PhysicalShapeLayer::Paint. - LayerRasterCacheKey key(unique_id(), context.Matrix()); - if (context.HasRetainedNode(key)) { - TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit"); - const scenic::EntityNode& retained_node = context.GetRetainedNode(key); - FML_DCHECK(context.top_entity()); - FML_DCHECK(retained_node.session() == context.session()); - context.top_entity()->entity_node().AddChild(retained_node); - return; - } + // If there is embedded Fuchsia content in the scene (a ChildSceneLayer), + // PhysicalShapeLayers that appear above the embedded content will be turned + // into their own Scenic layers. + if (child_layer_exists_below_) { + // Reset paint bounds, because shadows are not rendered in this case + // (see comment in Paint()). + set_paint_bounds(path_.getBounds()); + + float global_scenic_elevation = context.GetGlobalElevationForNextScenicLayer(); + float local_scenic_elevation_ = + global_scenic_elevation - context.scenic_elevation(); + float z_translation = -local_scenic_elevation_; + + // Retained rendering: speedup by reusing a retained entity node if + // possible. When an entity node is reused, no paint layer is added to the + // frame so we won't call PhysicalShapeLayer::Paint. + LayerRasterCacheKey key(unique_id(), context.Matrix()); + if (context.HasRetainedNode(key)) { + TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit"); + scenic::EntityNode* retained_node = context.GetRetainedNode(key); + FML_DCHECK(context.top_entity()); + FML_DCHECK(retained_node->session() == context.session()); - TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); - // If we can't find an existing retained surface, create one. - SceneUpdateContext::Frame frame(context, frameRRect_, color_, SK_AlphaOPAQUE, - elevation_, total_elevation_, this); - for (auto& layer : layers()) { - if (layer->needs_painting()) { - frame.AddPaintLayer(layer.get()); + // Re-adjust the elevation. + retained_node->SetTranslation(0.f, 0.f, z_translation); + + context.top_entity()->entity_node().AddChild(*retained_node); + return; + } + + TRACE_EVENT_INSTANT0("flutter", "cache miss, creating"); + // If we can't find an existing retained surface, create one. + SceneUpdateContext::Frame frame(context, frameRRect_, SK_ColorTRANSPARENT, + sk_float_round2int(context.alphaf() * 255), + "flutter::PhysicalShapeLayer", + z_translation, this); + + frame.AddPaintLayer(this); + + // Node: UpdateSceneChildren needs to be called here so that |frame| is still + // in scope (and therefore alive) while UpdateSceneChildren is being called. + if (children_need_system_compositing_) { + UpdateSceneChildren(context); + } + } else { + if (children_need_system_compositing_) { + UpdateSceneChildren(context); } } +} + +void PhysicalShapeLayer::UpdateSceneChildren(SceneUpdateContext& context) { + float scenic_elevation = context.scenic_elevation(); + context.set_scenic_elevation(scenic_elevation + local_scenic_elevation_); + + ContainerLayer::UpdateSceneChildren(context); - UpdateSceneChildren(context); + context.set_scenic_elevation(scenic_elevation); } #endif // defined(OS_FUCHSIA) @@ -110,7 +153,19 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint"); FML_DCHECK(needs_painting()); + +#if defined(OS_FUCHSIA) + // TODO: Re-enable shadow drawing here. + // Shadows are not rendered for PhysicalShapeLayers that exist as separate + // system services; this is to maintain compatibility with the previous + // implementation and has the added benefit of requiring smaller textures, since + // extra space is not needed for the shadows. + // This behavior might change after clients adjust their usage of PhysicalShaperLayer + // to make elevation correlate to desired shadow size. + if (false && !child_layer_exists_below_ && elevation_ != 0) { +#else if (elevation_ != 0) { +#endif DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_, SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio); } diff --git a/flow/layers/physical_shape_layer.h b/flow/layers/physical_shape_layer.h index 40ff19cfac348..b3ccfc4db1e8c 100644 --- a/flow/layers/physical_shape_layer.h +++ b/flow/layers/physical_shape_layer.h @@ -37,11 +37,18 @@ class PhysicalShapeLayer : public ContainerLayer { #if defined(OS_FUCHSIA) void UpdateScene(SceneUpdateContext& context) override; + + void UpdateSceneChildren(SceneUpdateContext& context); #endif // defined(OS_FUCHSIA) float total_elevation() const { return total_elevation_; } private: +#if defined(OS_FUCHSIA) + float local_scenic_elevation_ = 0.0f; + bool child_layer_exists_below_ = false; + bool children_need_system_compositing_ = false; +#endif SkColor color_; SkColor shadow_color_; float elevation_ = 0.0f; diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 5c7bc44073236..dea9b8f18ebd3 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -56,8 +56,12 @@ void TransformLayer::UpdateScene(SceneUpdateContext& context) { TRACE_EVENT0("flutter", "TransformLayer::UpdateScene"); FML_DCHECK(needs_system_composite()); - SceneUpdateContext::Transform transform(context, transform_); - UpdateSceneChildren(context); + if (!transform_.isIdentity()) { + SceneUpdateContext::Transform transform(context, transform_); + UpdateSceneChildren(context); + } else { + UpdateSceneChildren(context); + } } #endif // defined(OS_FUCHSIA) diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 59524bc9c6e56..1d8b536375221 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -4,6 +4,7 @@ #include "flutter/flow/scene_update_context.h" +#include #include "flutter/flow/layers/layer.h" #include "flutter/flow/matrix_decomposition.h" #include "flutter/fml/trace_event.h" @@ -72,14 +73,13 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node, // and possibly for its texture. // TODO(SCN-137): Need to be able to express the radii as vectors. scenic::ShapeNode shape_node(session()); - scenic::RoundedRectangle shape( - session_, // session - rrect.width(), // width - rrect.height(), // height - rrect.radii(SkRRect::kUpperLeft_Corner).x(), // top_left_radius - rrect.radii(SkRRect::kUpperRight_Corner).x(), // top_right_radius - rrect.radii(SkRRect::kLowerRight_Corner).x(), // bottom_right_radius - rrect.radii(SkRRect::kLowerLeft_Corner).x() // bottom_left_radius + scenic::RoundedRectangle shape(session_, // session + rrect.width(), // width + rrect.height(), // height + 0.f, // top_left_radius + 0.f, // top_right_radius + 0.f, // bottom_right_radius + 0.f // bottom_left_radius ); shape_node.SetShape(shape); shape_node.SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(), @@ -222,6 +222,9 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) { surfaces_to_submit.emplace_back(std::move(task.surface)); } paint_tasks_.clear(); + alpha_ = 1.f; + topmost_global_scenic_elevation_ = 10.f; + scenic_elevation_ = 0.f; return surfaces_to_submit; } @@ -244,19 +247,22 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context, : Entity(context), previous_scale_x_(context.top_scale_x_), previous_scale_y_(context.top_scale_y_) { + entity_node().SetLabel("flutter::Transform"); if (!transform.isIdentity()) { // TODO(SCN-192): The perspective and shear components in the matrix // are not handled correctly. MatrixDecomposition decomposition(transform); if (decomposition.IsValid()) { + // Don't allow clients to control the z dimension; we control that + // instead to make sure layers appear in proper order. entity_node().SetTranslation(decomposition.translation().x(), // decomposition.translation().y(), // - -decomposition.translation().z() // + 0.f // ); entity_node().SetScale(decomposition.scale().x(), // decomposition.scale().y(), // - decomposition.scale().z() // + 0.f // ); context.top_scale_x_ *= decomposition.scale().x(); context.top_scale_y_ *= decomposition.scale().y(); @@ -277,6 +283,7 @@ SceneUpdateContext::Transform::Transform(SceneUpdateContext& context, : Entity(context), previous_scale_x_(context.top_scale_x_), previous_scale_y_(context.top_scale_y_) { + entity_node().SetLabel("flutter::Transform"); if (scale_x != 1.f || scale_y != 1.f || scale_z != 1.f) { entity_node().SetScale(scale_x, scale_y, scale_z); context.top_scale_x_ *= scale_x; @@ -293,8 +300,8 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, const SkRRect& rrect, SkColor color, SkAlpha opacity, - float local_elevation, - float world_elevation, + std::string label, + float z_translation, Layer* layer) : Entity(context), rrect_(rrect), @@ -303,23 +310,14 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context, opacity_node_(context.session()), paint_bounds_(SkRect::MakeEmpty()), layer_(layer) { - const float depth = context.frame_physical_depth(); - if (depth > -1 && world_elevation > depth) { - // TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be - // able to have developers specify the behavior here to alternatives besides - // clamping, like normalization on some arbitrary curve. - - // Clamp the local z coordinate at our max bound. Take into account the - // parent z position here to fix clamping in cases where the child is - // overflowing because of its parents. - const float parent_elevation = world_elevation - local_elevation; - local_elevation = depth - parent_elevation; - } - if (local_elevation != 0.0) { - entity_node().SetTranslation(0.f, 0.f, -local_elevation); - } + entity_node().SetLabel(label); + entity_node().SetTranslation(0.f, 0.f, z_translation); entity_node().AddChild(opacity_node_); - opacity_node_.SetOpacity(opacity_ / 255.0f); + // Scenic currently lacks an API to enable rendering of alpha channel; this only happens + // if there is a OpacityNode higher in the tree with opacity != 1. For now, + // clamp to a infinitesimally smaller value than 1, which does not cause visual + // problems in practice. + opacity_node_.SetOpacity(std::min(1 - FLT_EPSILON, opacity_ / 255.0f)); } SceneUpdateContext::Frame::~Frame() { @@ -348,6 +346,7 @@ void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { SceneUpdateContext::Clip::Clip(SceneUpdateContext& context, const SkRect& shape_bounds) : Entity(context) { + entity_node().SetLabel("flutter::Clip"); SetEntityNodeClipPlanes(entity_node(), shape_bounds); } diff --git a/flow/scene_update_context.h b/flow/scene_update_context.h index 31bcb1bd57253..99da25136804e 100644 --- a/flow/scene_update_context.h +++ b/flow/scene_update_context.h @@ -59,8 +59,7 @@ class SceneUpdateContext { // Query a retained entity node (owned by a retained surface) for retained // rendering. virtual bool HasRetainedNode(const LayerRasterCacheKey& key) const = 0; - virtual const scenic::EntityNode& GetRetainedNode( - const LayerRasterCacheKey& key) = 0; + virtual scenic::EntityNode* GetRetainedNode(const LayerRasterCacheKey& key) = 0; virtual void SubmitSurface( std::unique_ptr surface) = 0; @@ -105,8 +104,8 @@ class SceneUpdateContext { const SkRRect& rrect, SkColor color, SkAlpha opacity, - float local_elevation = 0.0f, - float parent_elevation = 0.0f, + std::string label, + float z_translation = 0.0f, Layer* layer = nullptr); virtual ~Frame(); @@ -176,10 +175,25 @@ class SceneUpdateContext { bool HasRetainedNode(const LayerRasterCacheKey& key) const { return surface_producer_->HasRetainedNode(key); } - const scenic::EntityNode& GetRetainedNode(const LayerRasterCacheKey& key) { + scenic::EntityNode* GetRetainedNode(const LayerRasterCacheKey& key) { return surface_producer_->GetRetainedNode(key); } + // The cumulative alpha value based on all the parent OpacityLayers. + void set_alphaf(float alpha) { alpha_ = alpha; } + float alphaf() { return alpha_; } + + // The global scenic elevation at a given point in the traversal. + float scenic_elevation() { return scenic_elevation_; } + + void set_scenic_elevation(float elevation) { scenic_elevation_ = elevation; } + + float GetGlobalElevationForNextScenicLayer() { + float elevation = topmost_global_scenic_elevation_; + topmost_global_scenic_elevation_ += 10.f; + return elevation; + } + private: struct PaintTask { std::unique_ptr surface; @@ -237,6 +251,10 @@ class SceneUpdateContext { float frame_device_pixel_ratio_ = 1.0f; // Ratio between logical and physical pixels. + float alpha_ = 1.0f; + float scenic_elevation_ = 0.f; + float topmost_global_scenic_elevation_ = 10.f; + std::vector paint_tasks_; FML_DISALLOW_COPY_AND_ASSIGN(SceneUpdateContext); diff --git a/flow/view_holder.cc b/flow/view_holder.cc index 7f8929d933705..6962eeae7cbfa 100644 --- a/flow/view_holder.cc +++ b/flow/view_holder.cc @@ -102,13 +102,16 @@ ViewHolder::ViewHolder(fml::RefPtr ui_task_runner, void ViewHolder::UpdateScene(SceneUpdateContext& context, const SkPoint& offset, const SkSize& size, + SkAlpha opacity, bool hit_testable) { if (pending_view_holder_token_.value) { entity_node_ = std::make_unique(context.session()); + opacity_node_ = std::make_unique(context.session()); view_holder_ = std::make_unique( context.session(), std::move(pending_view_holder_token_), "Flutter SceneHost"); - + opacity_node_->AddChild(*entity_node_); + opacity_node_->SetLabel("flutter::ViewHolder"); entity_node_->Attach(*view_holder_); ui_task_runner_->PostTask( [bind_callback = std::move(pending_bind_callback_), @@ -117,9 +120,11 @@ void ViewHolder::UpdateScene(SceneUpdateContext& context, }); } FML_DCHECK(entity_node_); + FML_DCHECK(opacity_node_); FML_DCHECK(view_holder_); - context.top_entity()->embedder_node().AddChild(*entity_node_); + context.top_entity()->embedder_node().AddChild(*opacity_node_); + opacity_node_->SetOpacity(opacity / 255.0f); entity_node_->SetTranslation(offset.x(), offset.y(), -0.1f); entity_node_->SetHitTestBehavior( hit_testable ? fuchsia::ui::gfx::HitTestBehavior::kDefault diff --git a/flow/view_holder.h b/flow/view_holder.h index 82d43eba826d4..10677b8157680 100644 --- a/flow/view_holder.h +++ b/flow/view_holder.h @@ -57,12 +57,14 @@ class ViewHolder { void UpdateScene(SceneUpdateContext& context, const SkPoint& offset, const SkSize& size, + SkAlpha opacity, bool hit_testable); private: fml::RefPtr ui_task_runner_; std::unique_ptr entity_node_; + std::unique_ptr opacity_node_; std::unique_ptr view_holder_; fuchsia::ui::views::ViewHolderToken pending_view_holder_token_; diff --git a/shell/platform/fuchsia/flutter/vulkan_surface.h b/shell/platform/fuchsia/flutter/vulkan_surface.h index 4c67c9d5538c2..64dae4c4f9534 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface.h +++ b/shell/platform/fuchsia/flutter/vulkan_surface.h @@ -134,9 +134,9 @@ class VulkanSurface final // |EntityNode| associated with the retained surface instead of using the // retained surface directly. Hence Flutter can't modify the surface during // retained rendering. - const scenic::EntityNode& GetRetainedNode() { + scenic::EntityNode* GetRetainedNode() { used_in_retained_rendering_ = true; - return *retained_node_; + return retained_node_.get(); } // Check whether the retained surface (and its associated |EntityNode|) is diff --git a/shell/platform/fuchsia/flutter/vulkan_surface_pool.h b/shell/platform/fuchsia/flutter/vulkan_surface_pool.h index 00b40437de612..f3fb6727aed94 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface_pool.h +++ b/shell/platform/fuchsia/flutter/vulkan_surface_pool.h @@ -43,7 +43,7 @@ class VulkanSurfacePool final { return retained_surfaces_.find(key) != retained_surfaces_.end(); } // For |VulkanSurfaceProducer::GetRetainedNode|. - const scenic::EntityNode& GetRetainedNode( + scenic::EntityNode* GetRetainedNode( const flutter::LayerRasterCacheKey& key) { FML_DCHECK(HasRetainedNode(key)); return retained_surfaces_[key].vk_surface->GetRetainedNode(); diff --git a/shell/platform/fuchsia/flutter/vulkan_surface_producer.h b/shell/platform/fuchsia/flutter/vulkan_surface_producer.h index 77457bac32cdd..5ea1415cf537f 100644 --- a/shell/platform/fuchsia/flutter/vulkan_surface_producer.h +++ b/shell/platform/fuchsia/flutter/vulkan_surface_producer.h @@ -49,7 +49,7 @@ class VulkanSurfaceProducer final } // |flutter::SceneUpdateContext::GetRetainedNode| - const scenic::EntityNode& GetRetainedNode( + scenic::EntityNode* GetRetainedNode( const flutter::LayerRasterCacheKey& key) override { return surface_pool_->GetRetainedNode(key); }