[canvaskit] support adding leaf layers w/o container layers (flutter/engine#24357)

This commit is contained in:
Yegor 2021-02-12 11:03:56 -08:00 committed by GitHub
parent aff7e22b14
commit efa24d8bd0
5 changed files with 47 additions and 39 deletions

View File

@ -117,6 +117,17 @@ abstract class ContainerLayer extends Layer {
}
}
/// The top-most layer in the layer tree.
///
/// This layer does not draw anything. It's only used so we can add leaf layers
/// to [LayerSceneBuilder] without requiring a [ContainerLayer].
class RootLayer extends ContainerLayer {
@override
void paint(PaintContext context) {
paintChildren(context);
}
}
class BackdropFilterEngineLayer extends ContainerLayer implements ui.BackdropFilterEngineLayer {
final ui.ImageFilter _filter;

View File

@ -8,9 +8,7 @@ part of engine;
class LayerScene implements ui.Scene {
final LayerTree layerTree;
LayerScene(Layer? rootLayer) : layerTree = LayerTree() {
layerTree.rootLayer = rootLayer;
}
LayerScene(RootLayer rootLayer) : layerTree = LayerTree(rootLayer);
@override
void dispose() {}
@ -23,8 +21,12 @@ class LayerScene implements ui.Scene {
}
class LayerSceneBuilder implements ui.SceneBuilder {
Layer? rootLayer;
ContainerLayer? currentLayer;
LayerSceneBuilder() : rootLayer = RootLayer() {
currentLayer = rootLayer;
}
final RootLayer rootLayer;
late ContainerLayer currentLayer;
@override
void addChildScene({
@ -50,16 +52,13 @@ class LayerSceneBuilder implements ui.SceneBuilder {
bool isComplexHint = false,
bool willChangeHint = false,
}) {
currentLayer!.add(PictureLayer(
currentLayer.add(PictureLayer(
picture as CkPicture, offset, isComplexHint, willChangeHint));
}
@override
void addRetained(ui.EngineLayer retainedLayer) {
if (currentLayer == null) {
return;
}
currentLayer!.add(retainedLayer as Layer);
currentLayer.add(retainedLayer as Layer);
}
@override
@ -82,7 +81,7 @@ class LayerSceneBuilder implements ui.SceneBuilder {
double height = 0.0,
Object? webOnlyPaintedBy,
}) {
currentLayer!.add(PlatformViewLayer(viewId, offset, width, height));
currentLayer.add(PlatformViewLayer(viewId, offset, width, height));
}
@override
@ -92,10 +91,11 @@ class LayerSceneBuilder implements ui.SceneBuilder {
@override
void pop() {
if (currentLayer == null) {
if (currentLayer == rootLayer) {
// Don't pop the root layer. It must always be there.
return;
}
currentLayer = currentLayer!.parent;
currentLayer = currentLayer.parent!;
}
@override
@ -221,16 +221,7 @@ class LayerSceneBuilder implements ui.SceneBuilder {
}
T pushLayer<T extends ContainerLayer>(T layer) {
if (rootLayer == null) {
rootLayer = currentLayer = layer;
return layer;
}
if (currentLayer == null) {
return layer;
}
currentLayer!.add(layer);
currentLayer.add(layer);
currentLayer = layer;
return layer;
}

View File

@ -7,8 +7,10 @@ part of engine;
/// A tree of [Layer]s that, together with a [Size] compose a frame.
class LayerTree {
LayerTree(this.rootLayer);
/// The root of the layer tree.
Layer? rootLayer;
final RootLayer rootLayer;
/// The size (in physical pixels) of the frame to paint this layer tree into.
final ui.Size frameSize = ui.window.physicalSize;
@ -27,7 +29,7 @@ class LayerTree {
ignoreRasterCache ? null : frame.rasterCache,
frame.viewEmbedder,
);
rootLayer!.preroll(context, Matrix4.identity());
rootLayer.preroll(context, Matrix4.identity());
}
/// Paints the layer tree into the given [frame].
@ -48,8 +50,8 @@ class LayerTree {
ignoreRasterCache ? null : frame.rasterCache,
frame.viewEmbedder,
);
if (rootLayer!.needsPainting) {
rootLayer!.paint(context);
if (rootLayer.needsPainting) {
rootLayer.paint(context);
}
}
@ -59,17 +61,15 @@ class LayerTree {
ui.Picture flatten() {
CkPictureRecorder recorder = CkPictureRecorder();
CkCanvas canvas = recorder.beginRecording(ui.Rect.largest);
if (rootLayer != null) {
final PrerollContext prerollContext = PrerollContext(null, null);
rootLayer!.preroll(prerollContext, Matrix4.identity());
final PrerollContext prerollContext = PrerollContext(null, null);
rootLayer.preroll(prerollContext, Matrix4.identity());
CkNWayCanvas internalNodesCanvas = CkNWayCanvas();
internalNodesCanvas.addCanvas(canvas);
final PaintContext paintContext =
PaintContext(internalNodesCanvas, canvas, null, null);
if (rootLayer!.needsPainting) {
rootLayer!.paint(paintContext);
}
CkNWayCanvas internalNodesCanvas = CkNWayCanvas();
internalNodesCanvas.addCanvas(canvas);
final PaintContext paintContext =
PaintContext(internalNodesCanvas, canvas, null, null);
if (rootLayer.needsPainting) {
rootLayer.paint(paintContext);
}
return recorder.endRecording();
}

View File

@ -197,7 +197,7 @@ void testMain() {
// Render the scene once without painting the shadow bounds just to
// preroll the scene to compute the shadow bounds.
buildTestScene(paintShadowBounds: false).rootLayer!.preroll(
buildTestScene(paintShadowBounds: false).rootLayer.preroll(
PrerollContext(
RasterCache(),
HtmlViewEmbedder(),

View File

@ -44,12 +44,18 @@ void testMain() {
sb.addPicture(ui.Offset.zero, picture);
final LayerTree layerTree = sb.build().layerTree;
dispatcher.rasterizer!.draw(layerTree);
final ClipRectEngineLayer clipRect = layerTree.rootLayer as ClipRectEngineLayer;
final ClipRectEngineLayer clipRect = layerTree.rootLayer.debugLayers.single as ClipRectEngineLayer;
expect(clipRect.paintBounds, ui.Rect.fromLTRB(15, 15, 30, 30));
final TransformEngineLayer transform = clipRect.debugLayers.single as TransformEngineLayer;
expect(transform.paintBounds, ui.Rect.fromLTRB(0, 0, 30, 30));
});
test('can push a leaf layer without a container layer', () async {
final CkPictureRecorder recorder = CkPictureRecorder();
recorder.beginRecording(ui.Rect.zero);
LayerSceneBuilder().addPicture(ui.Offset.zero, recorder.endRecording());
});
// TODO: https://github.com/flutter/flutter/issues/60040
}, skip: isIosSafari);
}