Flutter Engine
performance_overlay_layer.cc
Go to the documentation of this file.
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 "flutter/flow/layers/performance_overlay_layer.h"
6 
7 #include <iomanip>
8 #include <iostream>
9 #include <string>
10 
11 #include "third_party/skia/include/core/SkFont.h"
12 #include "third_party/skia/include/core/SkTextBlob.h"
13 
14 namespace flutter {
15 namespace {
16 
17 void VisualizeStopWatch(SkCanvas* canvas,
18  const Stopwatch& stopwatch,
19  SkScalar x,
20  SkScalar y,
21  SkScalar width,
22  SkScalar height,
23  bool show_graph,
24  bool show_labels,
25  const std::string& label_prefix,
26  const std::string& font_path) {
27  const int label_x = 8; // distance from x
28  const int label_y = -10; // distance from y+height
29 
30  if (show_graph) {
31  SkRect visualization_rect = SkRect::MakeXYWH(x, y, width, height);
32  stopwatch.Visualize(canvas, visualization_rect);
33  }
34 
35  if (show_labels) {
37  stopwatch, label_prefix, font_path);
38  SkPaint paint;
39  paint.setColor(SK_ColorGRAY);
40  canvas->drawTextBlob(text, x + label_x, y + height + label_y, paint);
41  }
42 }
43 
44 } // namespace
45 
47  const Stopwatch& stopwatch,
48  const std::string& label_prefix,
49  const std::string& font_path) {
50  SkFont font;
51  if (font_path != "") {
52  font = SkFont(SkTypeface::MakeFromFile(font_path.c_str()));
53  }
54  font.setSize(15);
55 
56  double max_ms_per_frame = stopwatch.MaxDelta().ToMillisecondsF();
57  double average_ms_per_frame = stopwatch.AverageDelta().ToMillisecondsF();
58  std::stringstream stream;
59  stream.setf(std::ios::fixed | std::ios::showpoint);
60  stream << std::setprecision(1);
61  stream << label_prefix << " "
62  << "max " << max_ms_per_frame << " ms/frame, "
63  << "avg " << average_ms_per_frame << " ms/frame";
64  auto text = stream.str();
65  return SkTextBlob::MakeFromText(text.c_str(), text.size(), font,
66  SkTextEncoding::kUTF8);
67 }
68 
70  const char* font_path)
71  : options_(options) {
72  if (font_path != nullptr) {
73  font_path_ = font_path;
74  }
75 }
76 
78  const Layer* old_layer) {
79  DiffContext::AutoSubtreeRestore subtree(context);
80  if (!context->IsSubtreeDirty()) {
81  FML_DCHECK(old_layer);
82  auto prev = old_layer->as_performance_overlay_layer();
83  context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(prev));
84  }
85  context->AddLayerBounds(paint_bounds());
86  context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
87 }
88 
90  const int padding = 8;
91 
92  if (!options_) {
93  return;
94  }
95 
96  TRACE_EVENT0("flutter", "PerformanceOverlayLayer::Paint");
97  SkScalar x = paint_bounds().x() + padding;
98  SkScalar y = paint_bounds().y() + padding;
99  SkScalar width = paint_bounds().width() - (padding * 2);
100  SkScalar height = paint_bounds().height() / 2;
101  SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
102 
103  VisualizeStopWatch(
104  context.leaf_nodes_canvas, context.raster_time, x, y, width,
105  height - padding, options_ & kVisualizeRasterizerStatistics,
106  options_ & kDisplayRasterizerStatistics, "Raster", font_path_);
107 
108  VisualizeStopWatch(context.leaf_nodes_canvas, context.ui_time, x, y + height,
109  width, height - padding,
110  options_ & kVisualizeEngineStatistics,
111  options_ & kDisplayEngineStatistics, "UI", font_path_);
112 }
113 
114 } // namespace flutter
const Stopwatch & ui_time
Definition: layer.h:145
const int kDisplayRasterizerStatistics
void SetLayerPaintRegion(const Layer *layer, const PaintRegion &region)
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define FML_DCHECK(condition)
Definition: logging.h:86
void AddLayerBounds(const SkRect &rect)
virtual const PerformanceOverlayLayer * as_performance_overlay_layer() const
Definition: layer.h:275
const int kVisualizeEngineStatistics
const Stopwatch & raster_time
Definition: layer.h:144
PaintRegion GetOldLayerPaintRegion(const Layer *layer) const
void Diff(DiffContext *context, const Layer *old_layer) override
constexpr double ToMillisecondsF() const
Definition: time_delta.h:68
bool IsSubtreeDirty() const
Definition: diff_context.h:105
int32_t width
const SkRect & paint_bounds() const
Definition: layer.h:223
const int kVisualizeRasterizerStatistics
fml::TimeDelta AverageDelta() const
void Paint(PaintContext &context) const override
int32_t height
SkCanvas * leaf_nodes_canvas
Definition: layer.h:141
PerformanceOverlayLayer(uint64_t options, const char *font_path=nullptr)
const int kDisplayEngineStatistics
std::u16string text
fml::TimeDelta MaxDelta() const
PaintRegion CurrentSubtreeRegion() const
static sk_sp< SkTextBlob > MakeStatisticsText(const Stopwatch &stopwatch, const std::string &label_prefix, const std::string &font_path)
void MarkSubtreeDirty(const PaintRegion &previous_paint_region=PaintRegion())