// 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. /// /// Measures the performance of the `drawRect` operation. class BenchDrawRect extends SceneBuilderRecorder { /// A variant of the benchmark that uses the same [Paint] object for all rectangles. /// /// This variant focuses on the performance of the `drawRect` method itself. BenchDrawRect.staticPaint() : benchmarkPaint = false, super(name: benchmarkName); /// A variant of the benchmark that creates a unique [Paint] for each rectangle. /// /// Does not cache the [Paint] objects across frames, but generates new /// objects every time. This variant of the benchmark focuses on construction /// and transfer of paint data to the renderer. BenchDrawRect.variablePaint() : benchmarkPaint = true, super(name: variablePaintBenchmarkName); static const String benchmarkName = 'draw_rect'; static const String variablePaintBenchmarkName = 'draw_rect_variable_paint'; /// Number of rows in the grid. static const int kRows = 25; /// Number of columns in the grid. static const int kColumns = 40; /// Whether each cell should gets its own unique [Paint] value. /// /// This is used to benchmark the efficiency of passing a large number of /// paint objects to the rendering system. final bool benchmarkPaint; /// 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; static final Paint _staticPaint = Paint()..color = const Color.fromARGB(255, 255, 0, 0); Paint makePaint(int row, int col) { if (benchmarkPaint) { final Paint paint = Paint(); final double rowRatio = row / kRows; paint.color = Color.fromARGB(255, (255 * rowRatio).floor(), (255 * col / kColumns).floor(), 255); paint.filterQuality = FilterQuality.values[(FilterQuality.values.length * rowRatio).floor()]; paint.strokeCap = StrokeCap.values[(StrokeCap.values.length * rowRatio).floor()]; paint.strokeJoin = StrokeJoin.values[(StrokeJoin.values.length * rowRatio).floor()]; paint.blendMode = BlendMode.values[(BlendMode.values.length * rowRatio).floor()]; paint.style = PaintingStyle.values[(PaintingStyle.values.length * rowRatio).floor()]; paint.strokeWidth = 1.0 + rowRatio; paint.strokeMiterLimit = rowRatio; return paint; } else { return _staticPaint; } } @override void onDrawFrame(SceneBuilder sceneBuilder) { final PictureRecorder pictureRecorder = PictureRecorder(); final Canvas canvas = Canvas(pictureRecorder); final Size windowSize = window.physicalSize; final Size cellSize = Size( windowSize.width / kColumns, windowSize.height / kRows, ); final Size rectSize = cellSize * 0.8; for (int row = 0; row < kRows; row++) { canvas.save(); for (int col = 0; col < kColumns; col++) { canvas.drawRect( Offset((wobbleCounter - 5).abs(), 0) & rectSize, makePaint(row, col), ); canvas.translate(cellSize.width, 0); } canvas.restore(); canvas.translate(0, cellSize.height); } wobbleCounter += 1; wobbleCounter = wobbleCounter % 10; final Picture picture = pictureRecorder.endRecording(); sceneBuilder.pushOffset(0.0, 0.0); sceneBuilder.addPicture(Offset.zero, picture); sceneBuilder.pop(); } }