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

Commit 56d8ad3

Browse files
committed
[fuchsia] Composite PhysicalShapeLayers using Skia, except when they need to float above child views.
In that case, they will still need to be pulled into separate Scenic nodes to be composited on top of the child view[s].
1 parent f1341ec commit 56d8ad3

File tree

5 files changed

+93
-44
lines changed

5 files changed

+93
-44
lines changed

flow/layers/child_scene_layer.cc

Lines changed: 1 addition & 0 deletions
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) {

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/physical_shape_layer.cc

Lines changed: 72 additions & 35 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,37 +87,53 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
7887
FML_DCHECK(needs_system_composite());
7988
TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene");
8089

81-
float global_scenic_elevation =
82-
context.GetGlobalElevationForNextScenicLayer();
83-
float local_scenic_elevation_ =
84-
global_scenic_elevation - context.scenic_elevation();
85-
float z_translation = -local_scenic_elevation_;
86-
87-
// Retained rendering: speedup by reusing a retained entity node if possible.
88-
// When an entity node is reused, no paint layer is added to the frame so we
89-
// won't call PhysicalShapeLayer::Paint.
90-
LayerRasterCacheKey key(unique_id(), context.Matrix());
91-
if (context.HasRetainedNode(key)) {
92-
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
93-
scenic::EntityNode* retained_node = context.GetRetainedNode(key);
94-
FML_DCHECK(context.top_entity());
95-
FML_DCHECK(retained_node->session() == context.session());
96-
97-
// Re-adjust the elevation.
98-
retained_node->SetTranslation(0.f, 0.f, z_translation);
99-
100-
context.top_entity()->entity_node().AddChild(*retained_node);
101-
return;
102-
}
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());
10397

104-
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
105-
// If we can't find an existing retained surface, create one.
106-
SceneUpdateContext::Frame frame(
107-
context, frameRRect_, color_, sk_float_round2int(context.alphaf() * 255),
108-
"flutter::PhysicalShapeLayer", z_translation, this);
109-
for (auto& layer : layers()) {
110-
if (layer->needs_painting()) {
111-
frame.AddPaintLayer(layer.get());
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());
112+
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);
112137
}
113138
}
114139
}
@@ -128,7 +153,19 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
128153
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
129154
FML_DCHECK(needs_painting());
130155

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+
#else
131167
if (elevation_ != 0) {
168+
#endif
132169
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
133170
SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio);
134171
}

flow/layers/physical_shape_layer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ class PhysicalShapeLayer : public ContainerLayer {
4646
private:
4747
#if defined(OS_FUCHSIA)
4848
float local_scenic_elevation_ = 0.0f;
49+
bool child_layer_exists_below_ = false;
50+
bool children_need_system_compositing_ = false;
4951
#endif
5052
SkColor color_;
5153
SkColor shadow_color_;

flow/scene_update_context.cc

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "flutter/flow/scene_update_context.h"
66

7+
#include <cfloat>
78
#include "flutter/flow/layers/layer.h"
89
#include "flutter/flow/matrix_decomposition.h"
910
#include "flutter/fml/trace_event.h"
@@ -72,14 +73,13 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
7273
// and possibly for its texture.
7374
// TODO(SCN-137): Need to be able to express the radii as vectors.
7475
scenic::ShapeNode shape_node(session());
75-
scenic::RoundedRectangle shape(
76-
session_, // session
77-
rrect.width(), // width
78-
rrect.height(), // height
79-
rrect.radii(SkRRect::kUpperLeft_Corner).x(), // top_left_radius
80-
rrect.radii(SkRRect::kUpperRight_Corner).x(), // top_right_radius
81-
rrect.radii(SkRRect::kLowerRight_Corner).x(), // bottom_right_radius
82-
rrect.radii(SkRRect::kLowerLeft_Corner).x() // bottom_left_radius
76+
scenic::RoundedRectangle shape(session_, // session
77+
rrect.width(), // width
78+
rrect.height(), // height
79+
0.f, // top_left_radius
80+
0.f, // top_right_radius
81+
0.f, // bottom_right_radius
82+
0.f // bottom_left_radius
8383
);
8484
shape_node.SetShape(shape);
8585
shape_node.SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
@@ -313,7 +313,11 @@ SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
313313
entity_node().SetLabel(label);
314314
entity_node().SetTranslation(0.f, 0.f, z_translation);
315315
entity_node().AddChild(opacity_node_);
316-
opacity_node_.SetOpacity(opacity_ / 255.0f);
316+
// Scenic currently lacks an API to enable rendering of alpha channel; this only happens
317+
// if there is a OpacityNode higher in the tree with opacity != 1. For now,
318+
// clamp to a infinitesimally smaller value than 1, which does not cause visual
319+
// problems in practice.
320+
opacity_node_.SetOpacity(std::min(1 - FLT_EPSILON, opacity_ / 255.0f));
317321
}
318322

319323
SceneUpdateContext::Frame::~Frame() {

0 commit comments

Comments
 (0)