Unverified Commit febc6a14 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

remove forced compositing from opacity (#105334)

parent d5c62438
...@@ -13,6 +13,7 @@ import 'package:flutter/services.dart'; ...@@ -13,6 +13,7 @@ import 'package:flutter/services.dart';
import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart';
import 'box.dart'; import 'box.dart';
import 'debug.dart';
import 'layer.dart'; import 'layer.dart';
import 'layout_helper.dart'; import 'layout_helper.dart';
import 'object.dart'; import 'object.dart';
...@@ -884,16 +885,6 @@ class RenderOpacity extends RenderProxyBox { ...@@ -884,16 +885,6 @@ class RenderOpacity extends RenderProxyBox {
_alpha = ui.Color.getAlphaFromOpacity(opacity), _alpha = ui.Color.getAlphaFromOpacity(opacity),
super(child); super(child);
@override
bool get alwaysNeedsCompositing => child != null && (_alpha > 0);
@override
OffsetLayer updateCompositedLayer({required covariant OpacityLayer? oldLayer}) {
final OpacityLayer updatedLayer = oldLayer ?? OpacityLayer();
updatedLayer.alpha = _alpha;
return updatedLayer;
}
int _alpha; int _alpha;
/// The fraction to scale the child's alpha value. /// The fraction to scale the child's alpha value.
...@@ -914,13 +905,9 @@ class RenderOpacity extends RenderProxyBox { ...@@ -914,13 +905,9 @@ class RenderOpacity extends RenderProxyBox {
if (_opacity == value) { if (_opacity == value) {
return; return;
} }
final bool didNeedCompositing = alwaysNeedsCompositing;
final bool wasVisible = _alpha != 0; final bool wasVisible = _alpha != 0;
_opacity = value; _opacity = value;
_alpha = ui.Color.getAlphaFromOpacity(_opacity); _alpha = ui.Color.getAlphaFromOpacity(_opacity);
if (didNeedCompositing != alwaysNeedsCompositing) {
markNeedsCompositingBitsUpdate();
}
markNeedsPaint(); markNeedsPaint();
if (wasVisible != (_alpha != 0) && !alwaysIncludeSemantics) { if (wasVisible != (_alpha != 0) && !alwaysIncludeSemantics) {
markNeedsSemanticsUpdate(); markNeedsSemanticsUpdate();
...@@ -950,19 +937,40 @@ class RenderOpacity extends RenderProxyBox { ...@@ -950,19 +937,40 @@ class RenderOpacity extends RenderProxyBox {
@override @override
void paint(PaintingContext context, Offset offset) { void paint(PaintingContext context, Offset offset) {
if (child != null) { if (child == null) {
if (_alpha == 0) { return;
// No need to keep the layer. We'll create a new one if necessary. }
layer = null; if (_alpha == 0) {
return; // No need to keep the layer. We'll create a new one if necessary.
} layer = null;
assert(needsCompositing); return;
}
if (_alpha == 255) {
layer = null;
return super.paint(context, offset);
}
// Due to https://github.com/flutter/flutter/issues/48417 this will always need to be
// composited on the web.
if (needsCompositing || kIsWeb) {
layer = context.pushOpacity(offset, _alpha, super.paint, oldLayer: layer as OpacityLayer?); layer = context.pushOpacity(offset, _alpha, super.paint, oldLayer: layer as OpacityLayer?);
assert(() { assert(() {
layer!.debugCreator = debugCreator; layer?.debugCreator = debugCreator;
return true; return true;
}()); }());
return;
}
// debugDisableOpacityLayers is used by the SceneBuilder to remove opacity layers, but
// if the framework is not asked to composite will also need to remove the opacity here.
if (kDebugMode && debugDisableOpacityLayers) {
super.paint(context, offset);
return;
} }
final Color color = Color.fromRGBO(0, 0, 0, opacity);
final Canvas canvas = context.canvas;
canvas.saveLayer(size != null ? offset & size : null, Paint()..color = color);
super.paint(context, offset);
canvas.restore();
} }
@override @override
......
...@@ -197,7 +197,7 @@ void main() { ...@@ -197,7 +197,7 @@ void main() {
expect(data.lengthInBytes, equals(20 * 20 * 4)); expect(data.lengthInBytes, equals(20 * 20 * 4));
expect(data.elementSizeInBytes, equals(1)); expect(data.elementSizeInBytes, equals(1));
expect(getPixel(0, 0), equals(0x00000080)); expect(getPixel(0, 0), equals(0x0000007F));
expect(getPixel(image.width - 1, 0 ), equals(0xffffffff)); expect(getPixel(image.width - 1, 0 ), equals(0xffffffff));
final OffsetLayer layer = boundary.debugLayer! as OffsetLayer; final OffsetLayer layer = boundary.debugLayer! as OffsetLayer;
...@@ -206,7 +206,7 @@ void main() { ...@@ -206,7 +206,7 @@ void main() {
expect(image.width, equals(20)); expect(image.width, equals(20));
expect(image.height, equals(20)); expect(image.height, equals(20));
data = (await image.toByteData())!; data = (await image.toByteData())!;
expect(getPixel(0, 0), equals(0x00000080)); expect(getPixel(0, 0), equals(0x0000007F));
expect(getPixel(image.width - 1, 0 ), equals(0xffffffff)); expect(getPixel(image.width - 1, 0 ), equals(0xffffffff));
// non-zero offsets. // non-zero offsets.
...@@ -215,7 +215,7 @@ void main() { ...@@ -215,7 +215,7 @@ void main() {
expect(image.height, equals(30)); expect(image.height, equals(30));
data = (await image.toByteData())!; data = (await image.toByteData())!;
expect(getPixel(0, 0), equals(0x00000000)); expect(getPixel(0, 0), equals(0x00000000));
expect(getPixel(10, 10), equals(0x00000080)); expect(getPixel(10, 10), equals(0x0000007F));
expect(getPixel(image.width - 1, 0), equals(0x00000000)); expect(getPixel(image.width - 1, 0), equals(0x00000000));
expect(getPixel(image.width - 1, 10), equals(0xffffffff)); expect(getPixel(image.width - 1, 10), equals(0xffffffff));
...@@ -225,7 +225,7 @@ void main() { ...@@ -225,7 +225,7 @@ void main() {
expect(image.height, equals(60)); expect(image.height, equals(60));
data = (await image.toByteData())!; data = (await image.toByteData())!;
expect(getPixel(0, 0), equals(0x00000000)); expect(getPixel(0, 0), equals(0x00000000));
expect(getPixel(20, 20), equals(0x00000080)); expect(getPixel(20, 20), equals(0x0000007F));
expect(getPixel(image.width - 1, 0), equals(0x00000000)); expect(getPixel(image.width - 1, 0), equals(0x00000000));
expect(getPixel(image.width - 1, 20), equals(0xffffffff)); expect(getPixel(image.width - 1, 20), equals(0xffffffff));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/49857 }, skip: isBrowser); // https://github.com/flutter/flutter/issues/49857
...@@ -240,13 +240,13 @@ void main() { ...@@ -240,13 +240,13 @@ void main() {
expect(renderOpacity.needsCompositing, false); expect(renderOpacity.needsCompositing, false);
}); });
test('RenderOpacity does composite if it is opaque', () { test('RenderOpacity does not composite if it is opaque', () {
final RenderOpacity renderOpacity = RenderOpacity( final RenderOpacity renderOpacity = RenderOpacity(
child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter child: RenderSizedBox(const Size(1.0, 1.0)), // size doesn't matter
); );
layout(renderOpacity, phase: EnginePhase.composite); layout(renderOpacity, phase: EnginePhase.composite);
expect(renderOpacity.needsCompositing, true); expect(renderOpacity.needsCompositing, false);
}); });
test('RenderOpacity reuses its layer', () { test('RenderOpacity reuses its layer', () {
......
...@@ -285,8 +285,8 @@ void main() { ...@@ -285,8 +285,8 @@ void main() {
child: Placeholder(), child: Placeholder(),
), ),
const Opacity( const Opacity(
opacity: 1.0, opacity: 0.9, // ensure compositing is used.
child: Placeholder(), child: RepaintBoundary(child: Placeholder()),
), ),
ImageFiltered( ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), imageFilter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment