99
1010namespace flutter {
1111
12- OpacityLayer::OpacityLayer (int alpha, const SkPoint& offset)
13- : alpha_(alpha), offset_(offset) {
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 .0001f ;
16+
17+ #if !defined(OS_FUCHSIA)
18+ void OpacityLayerBase::Preroll (PrerollContext* context,
19+ const SkMatrix& matrix) {
20+ const float parent_is_opaque = context->is_opaque ;
21+
22+ context->mutators_stack .PushOpacity (opacity_);
23+ context->is_opaque = parent_is_opaque && (opacity_ == 255 );
24+ ContainerLayer::Preroll (context, matrix);
25+ context->is_opaque = parent_is_opaque;
26+ context->mutators_stack .Pop ();
27+ }
28+ #endif
29+
30+ OpacityLayer::OpacityLayer (SkAlpha opacity, const SkPoint& offset)
31+ : OpacityLayerBase(SK_ColorBLACK,
32+ opacity,
33+ kOpacityElevationWhenUsingSystemCompositor ),
34+ offset_ (offset) {
1435 // Ensure OpacityLayer has only one direct child.
1536 //
1637 // This is needed to ensure that retained rendering can always be applied to
@@ -31,15 +52,30 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
3152 ContainerLayer* container = GetChildContainer ();
3253 FML_DCHECK (!container->layers ().empty ()); // OpacityLayer can't be a leaf.
3354
55+ // Factor in the offset during Preroll. |OpacityLayerBase| will handle the
56+ // opacity.
3457 SkMatrix child_matrix = matrix;
3558 child_matrix.postTranslate (offset_.fX , offset_.fY );
3659 context->mutators_stack .PushTransform (
3760 SkMatrix::MakeTrans (offset_.fX , offset_.fY ));
38- context->mutators_stack .PushOpacity (alpha_);
39- ContainerLayer::Preroll (context, child_matrix);
40- context->mutators_stack .Pop ();
61+ OpacityLayerBase::Preroll (context, child_matrix);
4162 context->mutators_stack .Pop ();
42- set_paint_bounds (paint_bounds ().makeOffset (offset_.fX , offset_.fY ));
63+
64+ // When using the system compositor, do not include the offset since we are
65+ // rendering as a separate piece of geometry and the offset will be baked into
66+ // that geometry's transform.
67+ if (OpacityLayerBase::can_system_composite ()) {
68+ set_dimensions (SkRRect::MakeRect (paint_bounds ()));
69+
70+ // If the frame behind us is opaque, don't punch a hole in it for group
71+ // opacity.
72+ if (context->is_opaque ) {
73+ set_paint_bounds (SkRect::MakeEmpty ());
74+ }
75+ set_needs_system_composite (true );
76+ } else {
77+ set_paint_bounds (paint_bounds ().makeOffset (offset_.fX , offset_.fY ));
78+ }
4379
4480 if (!context->has_platform_view && context->raster_cache &&
4581 SkRect::Intersects (context->cull_rect , paint_bounds ())) {
@@ -51,12 +87,38 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
5187 }
5288}
5389
90+ #if defined(OS_FUCHSIA)
91+
92+ void OpacityLayer::UpdateScene (SceneUpdateContext& context) {
93+ SceneUpdateContext::Transform transform (
94+ context, SkMatrix::MakeTrans (offset_.fX , offset_.fY ));
95+
96+ // OpacityLayerBase will handle applying the opacity itself.
97+ OpacityLayerBase::UpdateScene (context);
98+ }
99+
100+ #endif
101+
54102void OpacityLayer::Paint (PaintContext& context) const {
55103 TRACE_EVENT0 (" flutter" , " OpacityLayer::Paint" );
56104 FML_DCHECK (needs_painting ());
57105
106+ // The compositor will paint this layer (which is |Sk_ColorBLACK| with alpha
107+ // scaled by opacity) via the model color on |SceneUpdateContext::Frame|.
108+ //
109+ // The child layers will be painted into the texture used by the Frame, so
110+ // painting them here would actually cause them to be painted on the display
111+ // twice -- once into the current canvas (which may be inside of another
112+ // Frame) and once into the Frame's texture (which is then drawn on top of the
113+ // current canvas).
114+ if (OpacityLayerBase::can_system_composite ()) {
115+ FML_DCHECK (needs_system_composite ());
116+ OpacityLayerBase::Paint (context);
117+ return ;
118+ }
119+
58120 SkPaint paint;
59- paint.setAlpha (alpha_ );
121+ paint.setAlpha (opacity () );
60122
61123 SkAutoCanvasRestore save (context.internal_nodes_canvas , true );
62124 context.internal_nodes_canvas ->translate (offset_.fX , offset_.fY );
@@ -83,16 +145,15 @@ void OpacityLayer::Paint(PaintContext& context) const {
83145 // RasterCache::GetIntegralTransCTM optimization.
84146 //
85147 // Note that the following lines are only accessible when the raster cache is
86- // not available (e.g., when we're using the software backend in golden
87- // tests).
148+ // not available, or when a cache miss occurs.
88149 SkRect saveLayerBounds;
89150 paint_bounds ()
90151 .makeOffset (-offset_.fX , -offset_.fY )
91152 .roundOut (&saveLayerBounds);
92153
93154 Layer::AutoSaveLayer save_layer =
94155 Layer::AutoSaveLayer::Create (context, saveLayerBounds, &paint);
95- PaintChildren (context);
156+ OpacityLayerBase::Paint (context);
96157}
97158
98159ContainerLayer* OpacityLayer::GetChildContainer () const {
0 commit comments