@@ -237,7 +237,25 @@ void DisplayListBuilder::restore() {
237237 layer_stack_.pop_back ();
238238 current_layer_ = &layer_stack_.back ();
239239 Push<RestoreOp>(0 , 1 );
240- if (!layer_info.has_layer ) {
240+ if (layer_info.has_layer ) {
241+ if (layer_info.is_group_opacity_compatible ()) {
242+ // We are now going to go back and modify the matching saveLayer
243+ // call to add the option indicating it can distribute an opacity
244+ // value to its children.
245+ //
246+ // Note that this operation cannot and does not change the size
247+ // or structure of the SaveLayerOp record. It only sets an option
248+ // flag on an existing field.
249+ //
250+ // Note that these kinds of modification operations on data already
251+ // in the DisplayList are only allowed *during* the build phase.
252+ // Once built, the DisplayList records must remain read only to
253+ // ensure consistency of rendering and |Equals()| behavior.
254+ SaveLayerOp* op = reinterpret_cast <SaveLayerOp*>(
255+ storage_.get () + layer_info.save_layer_offset );
256+ op->options = op->options .with_can_distribute_opacity ();
257+ }
258+ } else {
241259 // For regular save() ops there was no protecting layer so we have to
242260 // accumulate the values into the enclosing layer.
243261 if (layer_info.cannot_inherit_opacity ) {
@@ -249,13 +267,24 @@ void DisplayListBuilder::restore() {
249267 }
250268}
251269void DisplayListBuilder::saveLayer (const SkRect* bounds,
252- bool restore_with_paint) {
270+ const SaveLayerOptions in_options) {
271+ SaveLayerOptions options = in_options.without_optimizations ();
272+ size_t save_layer_offset = used_;
253273 bounds //
254- ? Push<SaveLayerBoundsOp>(0 , 1 , *bounds, restore_with_paint )
255- : Push<SaveLayerOp>(0 , 1 , restore_with_paint );
256- CheckLayerOpacityCompatibility (restore_with_paint );
257- layer_stack_.emplace_back (true );
274+ ? Push<SaveLayerBoundsOp>(0 , 1 , *bounds, options )
275+ : Push<SaveLayerOp>(0 , 1 , options );
276+ CheckLayerOpacityCompatibility (options. renders_with_attributes () );
277+ layer_stack_.emplace_back (save_layer_offset, true );
258278 current_layer_ = &layer_stack_.back ();
279+ if (options.renders_with_attributes ()) {
280+ // |current_opacity_compatibility_| does not take an ImageFilter into
281+ // account because an individual primitive with an ImageFilter can apply
282+ // opacity on top of it. But, if the layer is applying the ImageFilter
283+ // then it cannot pass the opacity on.
284+ if (!current_opacity_compatibility_ || current_image_filter_ != nullptr ) {
285+ UpdateLayerOpacityCompatibility (false );
286+ }
287+ }
259288}
260289
261290void DisplayListBuilder::translate (SkScalar tx, SkScalar ty) {
@@ -455,6 +484,8 @@ void DisplayListBuilder::drawVertices(const sk_sp<SkVertices> vertices,
455484 Push<DrawVerticesOp>(0 , 1 , std::move (vertices), mode);
456485 // DrawVertices applies its colors to the paint so we have no way
457486 // of controlling opacity using the current paint attributes.
487+ // Although, examination of the |mode| might find some predictable
488+ // cases.
458489 UpdateLayerOpacityCompatibility (false );
459490}
460491
0 commit comments