1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <iomanip>
6#include <iostream>
7#include <string>
8
9#include "flutter/flow/layers/performance_overlay_layer.h"
10#include "third_party/skia/include/core/SkFont.h"
11#include "third_party/skia/include/core/SkTextBlob.h"
12
13namespace flutter {
14namespace {
15
16void VisualizeStopWatch(SkCanvas* canvas,
17 const Stopwatch& stopwatch,
18 SkScalar x,
19 SkScalar y,
20 SkScalar width,
21 SkScalar height,
22 bool show_graph,
23 bool show_labels,
24 const std::string& label_prefix,
25 const std::string& font_path) {
26 const int label_x = 8; // distance from x
27 const int label_y = -10; // distance from y+height
28
29 if (show_graph) {
30 SkRect visualization_rect = SkRect::MakeXYWH(x, y, width, height);
31 stopwatch.Visualize(canvas, visualization_rect);
32 }
33
34 if (show_labels) {
35 auto text = PerformanceOverlayLayer::MakeStatisticsText(
36 stopwatch, label_prefix, font_path);
37 SkPaint paint;
38 paint.setColor(SK_ColorGRAY);
39 canvas->drawTextBlob(text, x + label_x, y + height + label_y, paint);
40 }
41}
42
43} // namespace
44
45sk_sp<SkTextBlob> PerformanceOverlayLayer::MakeStatisticsText(
46 const Stopwatch& stopwatch,
47 const std::string& label_prefix,
48 const std::string& font_path) {
49 SkFont font;
50 if (font_path != "") {
51 font = SkFont(SkTypeface::MakeFromFile(font_path.c_str()));
52 }
53 font.setSize(15);
54
55 double max_ms_per_frame = stopwatch.MaxDelta().ToMillisecondsF();
56 double average_ms_per_frame = stopwatch.AverageDelta().ToMillisecondsF();
57 std::stringstream stream;
58 stream.setf(std::ios::fixed | std::ios::showpoint);
59 stream << std::setprecision(1);
60 stream << label_prefix << " "
61 << "max " << max_ms_per_frame << " ms/frame, "
62 << "avg " << average_ms_per_frame << " ms/frame";
63 auto text = stream.str();
64 return SkTextBlob::MakeFromText(text.c_str(), text.size(), font,
65 SkTextEncoding::kUTF8);
66}
67
68PerformanceOverlayLayer::PerformanceOverlayLayer(uint64_t options,
69 const char* font_path)
70 : options_(options) {
71 if (font_path != nullptr) {
72 font_path_ = font_path;
73 }
74}
75
76void PerformanceOverlayLayer::Paint(PaintContext& context) const {
77 const int padding = 8;
78
79 if (!options_) {
80 return;
81 }
82
83 TRACE_EVENT0("flutter", "PerformanceOverlayLayer::Paint");
84 SkScalar x = paint_bounds().x() + padding;
85 SkScalar y = paint_bounds().y() + padding;
86 SkScalar width = paint_bounds().width() - (padding * 2);
87 SkScalar height = paint_bounds().height() / 2;
88 SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
89
90 VisualizeStopWatch(
91 context.leaf_nodes_canvas, context.raster_time, x, y, width,
92 height - padding, options_ & kVisualizeRasterizerStatistics,
93 options_ & kDisplayRasterizerStatistics, "Raster", font_path_);
94
95 VisualizeStopWatch(context.leaf_nodes_canvas, context.ui_time, x, y + height,
96 width, height - padding,
97 options_ & kVisualizeEngineStatistics,
98 options_ & kDisplayEngineStatistics, "UI", font_path_);
99}
100
101} // namespace flutter
102