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
@@ -43,15 +64,30 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
4364 ContainerLayer* container = GetChildContainer ();
4465 FML_DCHECK (!container->layers ().empty ()); // OpacityLayer can't be a leaf.
4566
67+ // Factor in the offset during Preroll. |OpacityLayerBase| will handle the
68+ // opacity.
4669 SkMatrix child_matrix = matrix;
4770 child_matrix.postTranslate (offset_.fX , offset_.fY );
4871 context->mutators_stack .PushTransform (
4972 SkMatrix::MakeTrans (offset_.fX , offset_.fY ));
50- context->mutators_stack .PushOpacity (alpha_);
51- ContainerLayer::Preroll (context, child_matrix);
52- context->mutators_stack .Pop ();
73+ OpacityLayerBase::Preroll (context, child_matrix);
5374 context->mutators_stack .Pop ();
54- set_paint_bounds (paint_bounds ().makeOffset (offset_.fX , offset_.fY ));
75+
76+ // When using the system compositor, do not include the offset since we are
77+ // rendering as a separate piece of geometry and the offset will be baked into
78+ // that geometry's transform.
79+ if (OpacityLayerBase::can_system_composite ()) {
80+ set_dimensions (SkRRect::MakeRect (paint_bounds ()));
81+
82+ // If the frame behind us is opaque, don't punch a hole in it for group
83+ // opacity.
84+ if (context->is_opaque ) {
85+ set_paint_bounds (SkRect::MakeEmpty ());
86+ }
87+ set_needs_system_composite (true );
88+ } else {
89+ set_paint_bounds (paint_bounds ().makeOffset (offset_.fX , offset_.fY ));
90+ }
5591
5692 if (!context->has_platform_view && context->raster_cache &&
5793 SkRect::Intersects (context->cull_rect , paint_bounds ())) {
@@ -63,12 +99,38 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
6399 }
64100}
65101
102+ #if defined(OS_FUCHSIA)
103+
104+ void OpacityLayer::UpdateScene (SceneUpdateContext& context) {
105+ SceneUpdateContext::Transform transform (
106+ context, SkMatrix::MakeTrans (offset_.fX , offset_.fY ));
107+
108+ // OpacityLayerBase will handle applying the opacity itself.
109+ OpacityLayerBase::UpdateScene (context);
110+ }
111+
112+ #endif
113+
66114void OpacityLayer::Paint (PaintContext& context) const {
67115 TRACE_EVENT0 (" flutter" , " OpacityLayer::Paint" );
68116 FML_DCHECK (needs_painting ());
69117
118+ // The compositor will paint this layer (which is |Sk_ColorBLACK| with alpha
119+ // scaled by opacity) via the model color on |SceneUpdateContext::Frame|.
120+ //
121+ // The child layers will be painted into the texture used by the Frame, so
122+ // painting them here would actually cause them to be painted on the display
123+ // twice -- once into the current canvas (which may be inside of another
124+ // Frame) and once into the Frame's texture (which is then drawn on top of the
125+ // current canvas).
126+ if (OpacityLayerBase::can_system_composite ()) {
127+ FML_DCHECK (needs_system_composite ());
128+ OpacityLayerBase::Paint (context);
129+ return ;
130+ }
131+
70132 SkPaint paint;
71- paint.setAlpha (alpha_ );
133+ paint.setAlpha (opacity () );
72134
73135 SkAutoCanvasRestore save (context.internal_nodes_canvas , true );
74136 context.internal_nodes_canvas ->translate (offset_.fX , offset_.fY );
@@ -95,16 +157,15 @@ void OpacityLayer::Paint(PaintContext& context) const {
95157 // RasterCache::GetIntegralTransCTM optimization.
96158 //
97159 // Note that the following lines are only accessible when the raster cache is
98- // not available (e.g., when we're using the software backend in golden
99- // tests).
160+ // not available, or when a cache miss occurs.
100161 SkRect saveLayerBounds;
101162 paint_bounds ()
102163 .makeOffset (-offset_.fX , -offset_.fY )
103164 .roundOut (&saveLayerBounds);
104165
105166 Layer::AutoSaveLayer save_layer =
106167 Layer::AutoSaveLayer::Create (context, saveLayerBounds, &paint);
107- PaintChildren (context);
168+ OpacityLayerBase::Paint (context);
108169}
109170
110171ContainerLayer* OpacityLayer::GetChildContainer () const {
0 commit comments