• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #include "StatsLayer.h"
9 
10 #include "SkCanvas.h"
11 #include "SkString.h"
12 #include "SkTime.h"
13 
StatsLayer()14 StatsLayer::StatsLayer()
15     : fCurrentMeasurement(0)
16     , fCumulativeMeasurementTime(0)
17     , fCumulativeMeasurementCount(0) {}
18 
resetMeasurements()19 void StatsLayer::resetMeasurements() {
20     for (int i = 0; i < fTimers.count(); ++i) {
21         memset(fTimers[i].fTimes, 0, sizeof(fTimers[i].fTimes));
22     }
23     fCurrentMeasurement = 0;
24     fCumulativeMeasurementTime = 0;
25     fCumulativeMeasurementCount = 0;
26 }
27 
addTimer(const char * label,SkColor color,SkColor labelColor)28 StatsLayer::Timer StatsLayer::addTimer(const char* label, SkColor color, SkColor labelColor) {
29     Timer newTimer = fTimers.count();
30     TimerData& newData = fTimers.push_back();
31     memset(newData.fTimes, 0, sizeof(newData.fTimes));
32     newData.fLabel = label;
33     newData.fColor = color;
34     newData.fLabelColor = labelColor ? labelColor : color;
35     return newTimer;
36 }
37 
beginTiming(Timer timer)38 void StatsLayer::beginTiming(Timer timer) {
39     fTimers[timer].fTimes[fCurrentMeasurement] -= SkTime::GetMSecs();
40 }
41 
endTiming(Timer timer)42 void StatsLayer::endTiming(Timer timer) {
43     fTimers[timer].fTimes[fCurrentMeasurement] += SkTime::GetMSecs();
44 }
45 
getLastTime(Timer timer)46 double StatsLayer::getLastTime(Timer timer) {
47     int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1);
48     return fTimers[timer].fTimes[idx];
49 }
50 
onPaint(SkCanvas * canvas)51 void StatsLayer::onPaint(SkCanvas* canvas) {
52     // Advance our timing bookkeeping
53     for (int i = 0; i < fTimers.count(); ++i) {
54         fCumulativeMeasurementTime += fTimers[i].fTimes[fCurrentMeasurement];
55     }
56     fCumulativeMeasurementCount++;
57     fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
58     SkASSERT(fCurrentMeasurement < kMeasurementCount);
59     for (int i = 0; i < fTimers.count(); ++i) {
60         fTimers[i].fTimes[fCurrentMeasurement] = 0;
61     }
62 
63     // Now draw everything
64     static const float kPixelPerMS = 2.0f;
65     static const int kDisplayWidth = 192;
66     static const int kGraphHeight = 100;
67     static const int kTextHeight = 60;
68     static const int kDisplayHeight = kGraphHeight + kTextHeight;
69     static const int kDisplayPadding = 10;
70     static const int kGraphPadding = 3;
71     static const SkScalar kBaseMS = 1000.f / 60.f;  // ms/frame to hit 60 fps
72 
73     SkISize canvasSize = canvas->getBaseLayerSize();
74     SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
75                                    SkIntToScalar(kDisplayPadding),
76                                    SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
77     SkPaint paint;
78     canvas->save();
79 
80     paint.setColor(SK_ColorBLACK);
81     canvas->drawRect(rect, paint);
82     // draw the 16ms line
83     paint.setColor(SK_ColorLTGRAY);
84     canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
85                      rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
86     paint.setColor(SK_ColorRED);
87     paint.setStyle(SkPaint::kStroke_Style);
88     canvas->drawRect(rect, paint);
89     paint.setStyle(SkPaint::kFill_Style);
90 
91     int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
92     const int xStep = 3;
93     int i = fCurrentMeasurement;
94     double ms = 0;
95     SkTDArray<double> sumTimes;
96     sumTimes.setCount(fTimers.count());
97     memset(sumTimes.begin(), 0, sumTimes.count() * sizeof(double));
98     int count = 0;
99     do {
100         int startY = SkScalarTruncToInt(rect.fBottom);
101         double inc = 0;
102         for (int timer = 0; timer < fTimers.count(); ++timer) {
103             int height = (int)(fTimers[timer].fTimes[i] * kPixelPerMS + 0.5);
104             int endY = SkTMax(startY - height, kDisplayPadding + kTextHeight);
105             paint.setColor(fTimers[timer].fColor);
106             canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
107                              SkIntToScalar(x), SkIntToScalar(endY), paint);
108             startY = endY;
109             inc += fTimers[timer].fTimes[i];
110             sumTimes[timer] += fTimers[timer].fTimes[i];
111         }
112 
113         if (inc > 0) {
114             ms += inc;
115             ++count;
116         }
117 
118         i++;
119         i &= (kMeasurementCount - 1);  // fast mod
120         x += xStep;
121     } while (i != fCurrentMeasurement);
122 
123     paint.setTextSize(16);
124     SkString mainString;
125     mainString.appendf("%4.3f ms -> %4.3f ms", ms / SkTMax(1, count),
126                   fCumulativeMeasurementTime / SkTMax(1, fCumulativeMeasurementCount));
127     paint.setColor(SK_ColorWHITE);
128     canvas->drawString(mainString.c_str(), rect.fLeft + 3, rect.fTop + 14, paint);
129 
130     for (int timer = 0; timer < fTimers.count(); ++timer) {
131         SkString str;
132         str.appendf("%s: %4.3f ms", fTimers[timer].fLabel.c_str(),
133                     sumTimes[timer] / SkTMax(1, count));
134         paint.setColor(fTimers[timer].fLabelColor);
135         canvas->drawString(str, rect.fLeft + 3, rect.fTop + 28 + (14 * timer), paint);
136     }
137 
138     canvas->restore();
139 }
140