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

Commit e371c1b

Browse files
committed
[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.
1 parent f2f8c34 commit e371c1b

15 files changed

+171
-116
lines changed

flow/layers/child_scene_layer.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id,
2020
void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
2121
TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll");
2222
set_needs_system_composite(true);
23+
context->child_scene_layer_exists_below = true;
2324

2425
// An alpha "hole punch" is required if the frame behind us is not opaque.
2526
if (!context->is_opaque) {
@@ -49,7 +50,9 @@ void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
4950
auto* view_holder = ViewHolder::FromId(layer_id_);
5051
FML_DCHECK(view_holder);
5152

52-
view_holder->UpdateScene(context, offset_, size_, hit_testable_);
53+
view_holder->UpdateScene(context, offset_, size_,
54+
sk_float_round2int(context.alphaf() * 255),
55+
hit_testable_);
5356
}
5457

5558
} // namespace flutter

flow/layers/layer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ struct PrerollContext {
6666
float total_elevation = 0.0f;
6767
bool has_platform_view = false;
6868
bool is_opaque = true;
69+
#if defined(OS_FUCHSIA)
70+
// True if, during the traversal so far, we have seen a child_scene_layer.
71+
// Informs whether a layer needs to be system composited.
72+
bool child_scene_layer_exists_below = false;
73+
#endif // defined(OS_FUCHSIA)
6974
};
7075

7176
// Represents a single composited layer. Created on the UI thread but then

flow/layers/layer_tree.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
8383
context,
8484
SkRRect::MakeRect(
8585
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
86-
SK_ColorTRANSPARENT, SK_AlphaOPAQUE);
86+
SK_ColorTRANSPARENT, SK_AlphaOPAQUE, "flutter::LayerTree");
8787
if (root_layer_->needs_system_composite()) {
8888
root_layer_->UpdateScene(context);
8989
}

flow/layers/opacity_layer.cc

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99

1010
namespace flutter {
1111

12-
// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting
13-
// when using the system compositor. Choose a small but non-zero value for
14-
// this.
15-
constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f;
16-
1712
OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset)
1813
: alpha_(alpha), offset_(offset) {
1914
// Ensure OpacityLayer has only one direct child.
@@ -40,8 +35,6 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
4035
SkMatrix child_matrix = matrix;
4136
child_matrix.postTranslate(offset_.fX, offset_.fY);
4237

43-
total_elevation_ = context->total_elevation;
44-
context->total_elevation += kOpacityElevationWhenUsingSystemCompositor;
4538
context->is_opaque = parent_is_opaque && (alpha_ == SK_AlphaOPAQUE);
4639
context->mutators_stack.PushTransform(
4740
SkMatrix::MakeTrans(offset_.fX, offset_.fY));
@@ -52,17 +45,7 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
5245
context->mutators_stack.Pop();
5346
context->mutators_stack.Pop();
5447
context->is_opaque = parent_is_opaque;
55-
context->total_elevation = total_elevation_;
5648

57-
#if defined(OS_FUCHSIA)
58-
if (needs_system_composite()) {
59-
// When using the system compositor, do not include the offset since we
60-
// are rendering as a separate piece of geometry and the offset will be
61-
// baked into that geometry's transform.
62-
frameRRect_ = SkRRect::MakeRect(paint_bounds());
63-
set_paint_bounds(SkRect::MakeEmpty());
64-
} else
65-
#endif
6649
{
6750
set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
6851
if (!context->has_platform_view && context->raster_cache &&
@@ -123,36 +106,10 @@ void OpacityLayer::Paint(PaintContext& context) const {
123106
#if defined(OS_FUCHSIA)
124107

125108
void OpacityLayer::UpdateScene(SceneUpdateContext& context) {
126-
FML_DCHECK(needs_system_composite());
127-
TRACE_EVENT0("flutter", "OpacityLayer::UpdateScene");
128-
129-
ContainerLayer* container = GetChildContainer();
130-
FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf.
131-
132-
SceneUpdateContext::Transform transform(
133-
context, SkMatrix::MakeTrans(offset_.fX, offset_.fY));
134-
135-
// Retained rendering: speedup by reusing a retained entity node if possible.
136-
// When an entity node is reused, no paint layer is added to the frame so we
137-
// won't call PhysicalShapeLayer::Paint.
138-
LayerRasterCacheKey key(unique_id(), context.Matrix());
139-
if (context.HasRetainedNode(key)) {
140-
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
141-
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
142-
FML_DCHECK(context.top_entity());
143-
FML_DCHECK(retained_node.session() == context.session());
144-
context.top_entity()->embedder_node().AddChild(retained_node);
145-
return;
146-
}
147-
148-
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
149-
// If we can't find an existing retained surface, create one.
150-
SceneUpdateContext::Frame frame(
151-
context, frameRRect_, SK_ColorTRANSPARENT, alpha_,
152-
kOpacityElevationWhenUsingSystemCompositor, total_elevation_, this);
153-
frame.AddPaintLayer(container);
154-
155-
UpdateSceneChildren(context);
109+
float saved_alpha = context.alphaf();
110+
context.set_alphaf(context.alphaf() * (alpha_ / 255.f));
111+
ContainerLayer::UpdateScene(context);
112+
context.set_alphaf(saved_alpha);
156113
}
157114

158115
#endif // defined(OS_FUCHSIA)

flow/layers/opacity_layer.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ class OpacityLayer : public ContainerLayer {
4343
SkAlpha alpha_;
4444
SkPoint offset_;
4545
SkRRect frameRRect_;
46-
float total_elevation_ = 0.0f;
4746

4847
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
4948
};

flow/layers/physical_shape_layer.cc

Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,32 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context,
5252

5353
context->total_elevation += elevation_;
5454
total_elevation_ = context->total_elevation;
55+
#if defined(OS_FUCHSIA)
56+
child_layer_exists_below_ = context->child_scene_layer_exists_below;
57+
context->child_scene_layer_exists_below = false;
58+
#endif
59+
5560
SkRect child_paint_bounds;
5661
PrerollChildren(context, matrix, &child_paint_bounds);
62+
63+
#if defined(OS_FUCHSIA)
64+
children_need_system_compositing_ = needs_system_composite();
65+
if (child_layer_exists_below_) {
66+
set_needs_system_composite(true);
67+
}
68+
context->child_scene_layer_exists_below =
69+
context->child_scene_layer_exists_below || child_layer_exists_below_;
70+
#endif
5771
context->total_elevation -= elevation_;
5872

5973
if (elevation_ == 0) {
6074
set_paint_bounds(path_.getBounds());
6175
} else {
62-
#if defined(OS_FUCHSIA)
63-
// Let the system compositor draw all shadows for us.
64-
set_needs_system_composite(true);
65-
#else
6676
// We will draw the shadow in Paint(), so add some margin to the paint
6777
// bounds to leave space for the shadow. We fill this whole region and clip
6878
// children to it so we don't need to join the child paint bounds.
6979
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_,
7080
context->frame_device_pixel_ratio));
71-
#endif // defined(OS_FUCHSIA)
7281
}
7382
}
7483

@@ -78,30 +87,64 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
7887
FML_DCHECK(needs_system_composite());
7988
TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene");
8089

81-
// Retained rendering: speedup by reusing a retained entity node if possible.
82-
// When an entity node is reused, no paint layer is added to the frame so we
83-
// won't call PhysicalShapeLayer::Paint.
84-
LayerRasterCacheKey key(unique_id(), context.Matrix());
85-
if (context.HasRetainedNode(key)) {
86-
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
87-
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
88-
FML_DCHECK(context.top_entity());
89-
FML_DCHECK(retained_node.session() == context.session());
90-
context.top_entity()->entity_node().AddChild(retained_node);
91-
return;
92-
}
90+
// If there is embedded Fuchsia content in the scene (a ChildSceneLayer),
91+
// PhysicalShapeLayers that appear above the embedded content will be turned
92+
// into their own Scenic layers.
93+
if (child_layer_exists_below_) {
94+
// Reset paint bounds, because shadows are not rendered in this case
95+
// (see comment in Paint()).
96+
set_paint_bounds(path_.getBounds());
97+
98+
float global_scenic_elevation = context.GetGlobalElevationForNextScenicLayer();
99+
float local_scenic_elevation_ =
100+
global_scenic_elevation - context.scenic_elevation();
101+
float z_translation = -local_scenic_elevation_;
102+
103+
// Retained rendering: speedup by reusing a retained entity node if
104+
// possible. When an entity node is reused, no paint layer is added to the
105+
// frame so we won't call PhysicalShapeLayer::Paint.
106+
LayerRasterCacheKey key(unique_id(), context.Matrix());
107+
if (context.HasRetainedNode(key)) {
108+
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
109+
scenic::EntityNode* retained_node = context.GetRetainedNode(key);
110+
FML_DCHECK(context.top_entity());
111+
FML_DCHECK(retained_node->session() == context.session());
93112

94-
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
95-
// If we can't find an existing retained surface, create one.
96-
SceneUpdateContext::Frame frame(context, frameRRect_, color_, SK_AlphaOPAQUE,
97-
elevation_, total_elevation_, this);
98-
for (auto& layer : layers()) {
99-
if (layer->needs_painting()) {
100-
frame.AddPaintLayer(layer.get());
113+
// Re-adjust the elevation.
114+
retained_node->SetTranslation(0.f, 0.f, z_translation);
115+
116+
context.top_entity()->entity_node().AddChild(*retained_node);
117+
return;
118+
}
119+
120+
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
121+
// If we can't find an existing retained surface, create one.
122+
SceneUpdateContext::Frame frame(context, frameRRect_, SK_ColorTRANSPARENT,
123+
sk_float_round2int(context.alphaf() * 255),
124+
"flutter::PhysicalShapeLayer",
125+
z_translation, this);
126+
127+
frame.AddPaintLayer(this);
128+
129+
// Node: UpdateSceneChildren needs to be called here so that |frame| is still
130+
// in scope (and therefore alive) while UpdateSceneChildren is being called.
131+
if (children_need_system_compositing_) {
132+
UpdateSceneChildren(context);
133+
}
134+
} else {
135+
if (children_need_system_compositing_) {
136+
UpdateSceneChildren(context);
101137
}
102138
}
139+
}
140+
141+
void PhysicalShapeLayer::UpdateSceneChildren(SceneUpdateContext& context) {
142+
float scenic_elevation = context.scenic_elevation();
143+
context.set_scenic_elevation(scenic_elevation + local_scenic_elevation_);
103144

104-
UpdateSceneChildren(context);
145+
ContainerLayer::UpdateSceneChildren(context);
146+
147+
context.set_scenic_elevation(scenic_elevation);
105148
}
106149

107150
#endif // defined(OS_FUCHSIA)
@@ -110,7 +153,20 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
110153
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
111154
FML_DCHECK(needs_painting());
112155

156+
157+
#if defined(OS_FUCHSIA)
158+
// TODO: Re-enable shadow drawing here.
159+
// Shadows are not rendered for PhysicalShapeLayers that exist as separate
160+
// system services; this is to maintain compatibility with the previous
161+
// implementation and has the added benefit of requiring smaller textures, since
162+
// extra space is not needed for the shadows.
163+
// This behavior might change after clients adjust their usage of PhysicalShaperLayer
164+
// to make elevation correlate to desired shadow size.
165+
//if (false && !child_layer_exists_below_ && elevation_ != 0) {
166+
if (elevation_ != 0) {
167+
#else
113168
if (elevation_ != 0) {
169+
#endif
114170
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
115171
SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio);
116172
}

flow/layers/physical_shape_layer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,18 @@ class PhysicalShapeLayer : public ContainerLayer {
3737

3838
#if defined(OS_FUCHSIA)
3939
void UpdateScene(SceneUpdateContext& context) override;
40+
41+
void UpdateSceneChildren(SceneUpdateContext& context);
4042
#endif // defined(OS_FUCHSIA)
4143

4244
float total_elevation() const { return total_elevation_; }
4345

4446
private:
47+
#if defined(OS_FUCHSIA)
48+
float local_scenic_elevation_ = 0.0f;
49+
bool child_layer_exists_below_ = false;
50+
bool children_need_system_compositing_ = false;
51+
#endif
4552
SkColor color_;
4653
SkColor shadow_color_;
4754
float elevation_ = 0.0f;

flow/layers/transform_layer.cc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ void TransformLayer::UpdateScene(SceneUpdateContext& context) {
5656
TRACE_EVENT0("flutter", "TransformLayer::UpdateScene");
5757
FML_DCHECK(needs_system_composite());
5858

59-
SceneUpdateContext::Transform transform(context, transform_);
60-
UpdateSceneChildren(context);
59+
if (!transform_.isIdentity()) {
60+
SceneUpdateContext::Transform transform(context, transform_);
61+
UpdateSceneChildren(context);
62+
} else {
63+
UpdateSceneChildren(context);
64+
}
6165
}
6266

6367
#endif // defined(OS_FUCHSIA)

0 commit comments

Comments
 (0)