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 14StatsLayer::StatsLayer() 15 : fCurrentMeasurement(0) 16 , fCumulativeMeasurementTime(0) 17 , fCumulativeMeasurementCount(0) {} 18 19void 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 28StatsLayer::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 38void StatsLayer::beginTiming(Timer timer) { 39 fTimers[timer].fTimes[fCurrentMeasurement] -= SkTime::GetMSecs(); 40} 41 42void StatsLayer::endTiming(Timer timer) { 43 fTimers[timer].fTimes[fCurrentMeasurement] += SkTime::GetMSecs(); 44} 45 46double StatsLayer::getLastTime(Timer timer) { 47 int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1); 48 return fTimers[timer].fTimes[idx]; 49} 50 51void 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