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

Commit 9eded82

Browse files
committed
Centralize system-composite and elevation logic
1 parent bd2793d commit 9eded82

13 files changed

+257
-110
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ FILE: ../../../flutter/flow/layers/color_filter_layer_unittests.cc
4848
FILE: ../../../flutter/flow/layers/container_layer.cc
4949
FILE: ../../../flutter/flow/layers/container_layer.h
5050
FILE: ../../../flutter/flow/layers/container_layer_unittests.cc
51+
FILE: ../../../flutter/flow/layers/elevated_container_layer.cc
52+
FILE: ../../../flutter/flow/layers/elevated_container_layer.h
53+
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.cc
54+
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.h
5155
FILE: ../../../flutter/flow/layers/layer.cc
5256
FILE: ../../../flutter/flow/layers/layer.h
5357
FILE: ../../../flutter/flow/layers/layer_tree.cc

flow/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ source_set("flow") {
2828
"layers/color_filter_layer.h",
2929
"layers/container_layer.cc",
3030
"layers/container_layer.h",
31+
"layers/elevated_container_layer.cc",
32+
"layers/elevated_container_layer.h",
3133
"layers/layer.cc",
3234
"layers/layer.h",
3335
"layers/layer_tree.cc",
@@ -76,6 +78,8 @@ source_set("flow") {
7678
sources += [
7779
"layers/child_scene_layer.cc",
7880
"layers/child_scene_layer.h",
81+
"layers/fuchsia_system_composited_layer.cc",
82+
"layers/fuchsia_system_composited_layer.h",
7983
"scene_update_context.cc",
8084
"scene_update_context.h",
8185
"view_holder.cc",

flow/layers/container_layer.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ void ContainerLayer::UpdateScene(SceneUpdateContext& context) {
9090
void ContainerLayer::UpdateSceneChildren(SceneUpdateContext& context) {
9191
FML_DCHECK(needs_system_composite());
9292

93-
// Paint all of the layers which need to be drawn into the container.
94-
// These may be flattened down to a containing
95-
for (auto& layer : layers_) {
93+
// Update all of the Layers which are part of the container. This may cause
94+
// additional child |Frame|s to be created.
95+
for (auto& layer : layers()) {
9696
if (layer->needs_system_composite()) {
9797
layer->UpdateScene(context);
9898
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/flow/layers/elevated_container_layer.h"
6+
7+
namespace flutter {
8+
namespace {
9+
10+
float ClampElevation(float elevation,
11+
float parent_elevation,
12+
float max_elevation) {
13+
// TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be
14+
// able to have developers specify the behavior here to alternatives besides
15+
// clamping, like normalization on some arbitrary curve.
16+
float clamped_elevation = elevation;
17+
if (max_elevation > -1 && (parent_elevation + elevation) > max_elevation) {
18+
// Clamp the local z coordinate at our max bound. Take into account the
19+
// parent z position here to fix clamping in cases where the child is
20+
// overflowing because of its parents.
21+
clamped_elevation = max_elevation - parent_elevation;
22+
}
23+
24+
return clamped_elevation;
25+
}
26+
27+
} // namespace
28+
29+
ElevatedContainerLayer::ElevatedContainerLayer(float elevation)
30+
: elevation_(elevation), clamped_elevation_(elevation) {}
31+
32+
void ElevatedContainerLayer::Preroll(PrerollContext* context,
33+
const SkMatrix& matrix) {
34+
TRACE_EVENT0("flutter", "ElevatedContainerLayer::Preroll");
35+
36+
// Track total elevation as we walk the tree, in order to deal with bounds
37+
// overflow in z.
38+
parent_elevation_ = context->total_elevation;
39+
clamped_elevation_ = ClampElevation(elevation_, parent_elevation_,
40+
context->frame_physical_depth);
41+
context->total_elevation += clamped_elevation_;
42+
43+
ContainerLayer::Preroll(context, matrix);
44+
45+
// Restore the elevation for our parent.
46+
context->total_elevation = parent_elevation_;
47+
}
48+
49+
} // namespace flutter
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
6+
#define FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
7+
8+
#include "flutter/flow/layers/container_layer.h"
9+
10+
namespace flutter {
11+
12+
class ElevatedContainerLayer : public ContainerLayer {
13+
public:
14+
ElevatedContainerLayer(float elevation);
15+
~ElevatedContainerLayer() override = default;
16+
17+
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
18+
19+
float elevation() const { return clamped_elevation_; }
20+
float total_elevation() const {
21+
return parent_elevation_ + clamped_elevation_;
22+
}
23+
24+
private:
25+
float parent_elevation_ = 0.0f;
26+
float elevation_ = 0.0f;
27+
float clamped_elevation_ = 0.0f;
28+
29+
FML_DISALLOW_COPY_AND_ASSIGN(ElevatedContainerLayer);
30+
};
31+
32+
} // namespace flutter
33+
34+
#endif // FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
6+
7+
namespace flutter {
8+
9+
FuchsiaSystemCompositedLayer::FuchsiaSystemCompositedLayer(SkColor color,
10+
float elevation)
11+
: ElevatedContainerLayer(elevation), color_(color) {}
12+
13+
void FuchsiaSystemCompositedLayer::Preroll(PrerollContext* context,
14+
const SkMatrix& matrix) {
15+
TRACE_EVENT0("flutter", "FuchsiaSystemCompositedLayer::Preroll");
16+
17+
ElevatedContainerLayer::Preroll(context, matrix);
18+
19+
// System-composite this layer if its elevated.
20+
if (elevation() != 0.0f) {
21+
set_needs_system_composite(true);
22+
set_paint_bounds(SkRect::MakeEmpty());
23+
}
24+
}
25+
26+
void FuchsiaSystemCompositedLayer::UpdateScene(SceneUpdateContext& context) {
27+
FML_DCHECK(needs_system_composite());
28+
29+
// Retained rendering: speedup by reusing a retained entity node if
30+
// possible. When an entity node is reused, no paint layer is added to the
31+
// frame so we won't call Paint.
32+
LayerRasterCacheKey key(unique_id(), context.Matrix());
33+
if (context.HasRetainedNode(key)) {
34+
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
35+
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
36+
FML_DCHECK(context.top_entity());
37+
FML_DCHECK(retained_node.session() == context.session());
38+
context.top_entity()->embedder_node().AddChild(retained_node);
39+
return;
40+
}
41+
42+
TRACE_EVENT_INSTANT0("flutter", "retained cache miss, creating");
43+
// If we can't find an existing retained surface, create one.
44+
SceneUpdateContext::Frame frame(context, rrect_, color_, elevation(), this);
45+
for (auto& layer : layers()) {
46+
if (layer->needs_painting()) {
47+
frame.AddPaintLayer(layer.get());
48+
}
49+
}
50+
51+
ContainerLayer::UpdateScene(context);
52+
}
53+
54+
} // namespace flutter
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
6+
#define FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
7+
8+
#include "flutter/flow/layers/elevated_container_layer.h"
9+
10+
namespace flutter {
11+
12+
class FuchsiaSystemCompositedLayer : public ElevatedContainerLayer {
13+
public:
14+
static bool can_system_composite() { return true; }
15+
16+
FuchsiaSystemCompositedLayer(SkColor color, float elevation);
17+
18+
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
19+
void UpdateScene(SceneUpdateContext& context) override;
20+
21+
void set_dimensions(SkRRect rrect) { rrect_ = rrect; }
22+
23+
SkColor color() const { return color_; }
24+
25+
private:
26+
SkRRect rrect_ = SkRRect::MakeEmpty();
27+
SkColor color_ = SK_ColorTRANSPARENT;
28+
29+
FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedLayer);
30+
};
31+
32+
} // namespace flutter
33+
34+
#endif // FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_

flow/layers/layer_tree.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
8989
context,
9090
SkRRect::MakeRect(
9191
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
92-
SK_ColorTRANSPARENT);
92+
SK_ColorTRANSPARENT, /* elevation */ 0.0f);
9393
if (root_layer_->needs_system_composite()) {
9494
root_layer_->UpdateScene(context);
9595
}

flow/layers/physical_shape_layer.cc

Lines changed: 32 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,35 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
1717
float elevation,
1818
const SkPath& path,
1919
Clip clip_behavior)
20-
: color_(color),
20+
: PhysicalShapeLayerBase(color, elevation),
2121
shadow_color_(shadow_color),
22-
elevation_(elevation),
2322
path_(path),
24-
isRect_(false),
2523
clip_behavior_(clip_behavior) {
24+
// If rendering as a separate frame using the system compositor, then make
25+
// sure to set up the properties needed to do so.
26+
#if defined(OS_FUCHSIA)
2627
SkRect rect;
28+
SkRRect rrect;
2729
if (path.isRect(&rect)) {
28-
isRect_ = true;
29-
frameRRect_ = SkRRect::MakeRect(rect);
30-
} else if (path.isRRect(&frameRRect_)) {
31-
isRect_ = frameRRect_.isRect();
30+
rrect = SkRRect::MakeRect(rect);
31+
} else if (path.isRRect(&rrect)) {
32+
// Nothing needed here, as isRRect will fill in frameRRect_ already.
3233
} else if (path.isOval(&rect)) {
3334
// isRRect returns false for ovals, so we need to explicitly check isOval
3435
// as well.
35-
frameRRect_ = SkRRect::MakeOval(rect);
36+
rrect = SkRRect::MakeOval(rect);
3637
} else {
3738
// Scenic currently doesn't provide an easy way to create shapes from
3839
// arbitrary paths.
3940
// For shapes that cannot be represented as a rounded rectangle we
4041
// default to use the bounding rectangle.
4142
// TODO(amirh): fix this once we have a way to create a Scenic shape from
4243
// an SkPath.
43-
frameRRect_ = SkRRect::MakeRect(path.getBounds());
44+
rrect = SkRRect::MakeRect(path.getBounds());
4445
}
46+
47+
set_dimensions(rrect);
48+
#endif
4549
}
4650

4751
Layer::AnalysisResult PhysicalShapeLayer::Analyze() const {
@@ -55,74 +59,39 @@ Layer::AnalysisResult PhysicalShapeLayer::Analyze() const {
5559
void PhysicalShapeLayer::Preroll(PrerollContext* context,
5660
const SkMatrix& matrix) {
5761
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Preroll");
58-
context->total_elevation += elevation_;
59-
total_elevation_ = context->total_elevation;
60-
SkRect child_paint_bounds;
61-
PrerollChildren(context, matrix, &child_paint_bounds);
62-
context->total_elevation -= elevation_;
63-
64-
if (elevation_ == 0) {
65-
set_paint_bounds(path_.getBounds());
66-
} else {
67-
#if defined(OS_FUCHSIA)
68-
// Let the system compositor draw all shadows for us.
69-
set_needs_system_composite(true);
70-
#else
71-
// We will draw the shadow in Paint(), so add some margin to the paint
72-
// bounds to leave space for the shadow. We fill this whole region and clip
73-
// children to it so we don't need to join the child paint bounds.
74-
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_,
75-
context->frame_device_pixel_ratio));
76-
#endif // defined(OS_FUCHSIA)
77-
}
78-
}
79-
80-
#if defined(OS_FUCHSIA)
62+
PhysicalShapeLayerBase::Preroll(context, matrix);
8163

82-
void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
83-
FML_DCHECK(needs_system_composite());
84-
TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene");
85-
86-
// Retained rendering: speedup by reusing a retained entity node if possible.
87-
// When an entity node is reused, no paint layer is added to the frame so we
88-
// won't call PhysicalShapeLayer::Paint.
89-
LayerRasterCacheKey key(unique_id(), context.Matrix());
90-
if (context.HasRetainedNode(key)) {
91-
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
92-
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
93-
FML_DCHECK(context.top_entity());
94-
FML_DCHECK(retained_node.session() == context.session());
95-
context.top_entity()->entity_node().AddChild(retained_node);
64+
// Use the system compositor for shadows if it's available. 0-elevation
65+
// doesn't cast shadows, so it never uses the system compositor.
66+
if (PhysicalShapeLayerBase::can_system_composite() && elevation() != 0) {
9667
return;
9768
}
9869

99-
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
100-
// If we can't find an existing retained surface, create one.
101-
SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_,
102-
total_elevation_, this);
103-
for (auto& layer : layers()) {
104-
if (layer->needs_painting()) {
105-
frame.AddPaintLayer(layer.get());
106-
}
70+
// We either can't (unavailable) or shouldn't (no shadows) use the system
71+
// compositor.
72+
set_needs_system_composite(false);
73+
set_paint_bounds(path_.getBounds()); // Ignore children bounds; use the path
74+
if (elevation() != 0) {
75+
// We will draw the shadow in Paint(), so add some margin to the paint
76+
// bounds to leave space for the shadow. We fill this whole region and clip
77+
// children to it so we don't need to join the child paint bounds.
78+
set_paint_bounds(ComputeShadowBounds(paint_bounds(), elevation(),
79+
context->frame_device_pixel_ratio));
10780
}
108-
109-
UpdateSceneChildren(context);
11081
}
11182

112-
#endif // defined(OS_FUCHSIA)
113-
11483
void PhysicalShapeLayer::Paint(PaintContext& context) const {
11584
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
11685
FML_DCHECK(needs_painting());
11786

118-
if (elevation_ != 0) {
119-
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
120-
SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio);
87+
if (elevation() != 0) {
88+
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation(),
89+
SkColorGetA(color()) != 0xff, context.frame_device_pixel_ratio);
12190
}
12291

12392
// Call drawPath without clip if possible for better performance.
12493
SkPaint paint;
125-
paint.setColor(color_);
94+
paint.setColor(color());
12695
paint.setAntiAlias(true);
12796
if (clip_behavior_ != Clip::antiAliasWithSaveLayer) {
12897
context.leaf_nodes_canvas->drawPath(path_, paint);
@@ -152,7 +121,7 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
152121
context.leaf_nodes_canvas->drawPaint(paint);
153122
}
154123

155-
PaintChildren(context);
124+
PhysicalShapeLayerBase::Paint(context);
156125

157126
context.internal_nodes_canvas->restoreToCount(saveCount);
158127
}

0 commit comments

Comments
 (0)