blob: 56672a075ba384384095dcd8c63fd92c9936f504 [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:ui';
import 'recorder.dart';
/// Repeatedly paints a grid of rectangles where each rectangle is drawn in its
/// own [Picture].
///
/// Measures the performance of updating many layers. For example, the HTML
/// rendering backend attempts to reuse the DOM nodes created for engine layers.
///
/// See also `bench_draw_rect.dart`, which draws nearly identical UI but puts all
/// rectangles into the same picture.
class BenchUpdateManyChildLayers extends SceneBuilderRecorder {
BenchUpdateManyChildLayers() : super(name: benchmarkName);
static const String benchmarkName = 'bench_update_many_child_layers';
/// Number of rows in the grid.
static const int kRows = 32;
/// Number of columns in the grid.
static const int kColumns = 32;
/// Counter used to offset the rendered rects to make them wobble.
///
/// The wobbling is there so a human could visually verify that the benchmark
/// is correctly pumping frames.
double wobbleCounter = 0;
List<Picture> _pictures;
Size windowSize;
Size cellSize;
Size rectSize;
@override
Future<void> setUpAll() async {
_pictures = <Picture>[];
windowSize = window.physicalSize;
cellSize = Size(
windowSize.width / kColumns,
windowSize.height / kRows,
);
rectSize = cellSize * 0.8;
final Paint paint = Paint()..color = const Color.fromARGB(255, 255, 0, 0);
for (int i = 0; i < kRows * kColumns; i++) {
final PictureRecorder pictureRecorder = PictureRecorder();
final Canvas canvas = Canvas(pictureRecorder);
canvas.drawRect(Offset.zero & rectSize, paint);
_pictures.add(pictureRecorder.endRecording());
}
}
OffsetEngineLayer _rootLayer;
final Map<int, OffsetEngineLayer> _layers = <int, OffsetEngineLayer>{};
@override
void onDrawFrame(SceneBuilder sceneBuilder) {
_rootLayer = sceneBuilder.pushOffset(0, 0, oldLayer: _rootLayer);
for (int row = 0; row < kRows; row++) {
for (int col = 0; col < kColumns; col++) {
final int layerId = 1000000 * row + col;
final OffsetEngineLayer oldLayer = _layers[layerId];
final double wobbleOffsetX = col * cellSize.width + (wobbleCounter - 5).abs();
final double offsetY = row * cellSize.height;
// Retain every other layer, so we exercise the update path 50% of the
// time and the retain path the other 50%.
final bool shouldRetain = oldLayer != null && (row + col) % 2 == 0;
if (shouldRetain) {
sceneBuilder.addRetained(oldLayer);
} else {
_layers[layerId] = sceneBuilder.pushOffset(
wobbleOffsetX,
offsetY,
oldLayer: oldLayer,
);
sceneBuilder.addPicture(Offset.zero, _pictures[row * kColumns + col]);
sceneBuilder.pop();
}
}
}
sceneBuilder.pop();
wobbleCounter += 1;
wobbleCounter = wobbleCounter % 10;
}
}