Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[fuchsia] Avoid creating separate system layers for PhysicalShapeLayers. #16975

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion flow/layers/child_scene_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
5 changes: 5 additions & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
51 changes: 4 additions & 47 deletions flow/layers/opacity_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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));
Expand All @@ -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 &&
Expand Down Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion flow/layers/opacity_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
Expand Down
105 changes: 80 additions & 25 deletions flow/layers/physical_shape_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand All @@ -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)
Expand All @@ -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);
}
Expand Down
7 changes: 7 additions & 0 deletions flow/layers/physical_shape_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 6 additions & 2 deletions flow/layers/transform_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading