| 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 | |
| 13 | namespace flutter { |
| 14 | namespace { |
| 15 | |
| 16 | void 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 | |
| 45 | sk_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 | |
| 68 | PerformanceOverlayLayer::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 | |
| 76 | void 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 | |