StatsLayer.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include "tools/viewer/StatsLayer.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkFont.h"
  10. #include "include/core/SkString.h"
  11. #include "include/core/SkSurface.h"
  12. #include "include/core/SkTime.h"
  13. StatsLayer::StatsLayer()
  14. : fCurrentMeasurement(-1)
  15. , fLastTotalBegin(0)
  16. , fCumulativeMeasurementTime(0)
  17. , fCumulativeMeasurementCount(0)
  18. , fDisplayScale(1.0f) {
  19. memset(fTotalTimes, 0, sizeof(fTotalTimes));
  20. }
  21. void StatsLayer::resetMeasurements() {
  22. for (int i = 0; i < fTimers.count(); ++i) {
  23. memset(fTimers[i].fTimes, 0, sizeof(fTimers[i].fTimes));
  24. }
  25. memset(fTotalTimes, 0, sizeof(fTotalTimes));
  26. fCurrentMeasurement = -1;
  27. fLastTotalBegin = 0;
  28. fCumulativeMeasurementTime = 0;
  29. fCumulativeMeasurementCount = 0;
  30. }
  31. StatsLayer::Timer StatsLayer::addTimer(const char* label, SkColor color, SkColor labelColor) {
  32. Timer newTimer = fTimers.count();
  33. TimerData& newData = fTimers.push_back();
  34. memset(newData.fTimes, 0, sizeof(newData.fTimes));
  35. newData.fLabel = label;
  36. newData.fColor = color;
  37. newData.fLabelColor = labelColor ? labelColor : color;
  38. return newTimer;
  39. }
  40. void StatsLayer::beginTiming(Timer timer) {
  41. if (fCurrentMeasurement >= 0) {
  42. fTimers[timer].fTimes[fCurrentMeasurement] -= SkTime::GetMSecs();
  43. }
  44. }
  45. void StatsLayer::endTiming(Timer timer) {
  46. if (fCurrentMeasurement >= 0) {
  47. fTimers[timer].fTimes[fCurrentMeasurement] += SkTime::GetMSecs();
  48. }
  49. }
  50. void StatsLayer::onPrePaint() {
  51. if (fCurrentMeasurement >= 0) {
  52. fTotalTimes[fCurrentMeasurement] = SkTime::GetMSecs() - fLastTotalBegin;
  53. fCumulativeMeasurementTime += fTotalTimes[fCurrentMeasurement];
  54. fCumulativeMeasurementCount++;
  55. }
  56. fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
  57. SkASSERT(fCurrentMeasurement >= 0 && fCurrentMeasurement < kMeasurementCount);
  58. fLastTotalBegin = SkTime::GetMSecs();
  59. }
  60. void StatsLayer::onPaint(SkSurface* surface) {
  61. int nextMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
  62. for (int i = 0; i < fTimers.count(); ++i) {
  63. fTimers[i].fTimes[nextMeasurement] = 0;
  64. }
  65. #ifdef SK_BUILD_FOR_ANDROID
  66. // Scale up the stats overlay on Android devices
  67. static constexpr SkScalar kScale = 1.5;
  68. #else
  69. SkScalar kScale = fDisplayScale;
  70. #endif
  71. // Now draw everything
  72. static const float kPixelPerMS = 2.0f;
  73. static const int kDisplayWidth = 192;
  74. static const int kGraphHeight = 100;
  75. static const int kTextHeight = 60;
  76. static const int kDisplayHeight = kGraphHeight + kTextHeight;
  77. static const int kDisplayPadding = 10;
  78. static const int kGraphPadding = 3;
  79. static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
  80. auto canvas = surface->getCanvas();
  81. SkISize canvasSize = canvas->getBaseLayerSize();
  82. SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
  83. SkIntToScalar(kDisplayPadding),
  84. SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
  85. SkPaint paint;
  86. canvas->save();
  87. // Scale the canvas while keeping the right edge in place.
  88. canvas->concat(SkMatrix::MakeRectToRect(SkRect::Make(canvasSize),
  89. SkRect::MakeXYWH(canvasSize.width() * (1 - kScale),
  90. 0,
  91. canvasSize.width() * kScale,
  92. canvasSize.height() * kScale),
  93. SkMatrix::kFill_ScaleToFit));
  94. paint.setColor(SK_ColorBLACK);
  95. canvas->drawRect(rect, paint);
  96. // draw the 16ms line
  97. paint.setColor(SK_ColorLTGRAY);
  98. canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
  99. rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
  100. paint.setColor(SK_ColorRED);
  101. paint.setStyle(SkPaint::kStroke_Style);
  102. canvas->drawRect(rect, paint);
  103. paint.setStyle(SkPaint::kFill_Style);
  104. int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
  105. const int xStep = 3;
  106. int i = nextMeasurement;
  107. SkTDArray<double> sumTimes;
  108. sumTimes.setCount(fTimers.count());
  109. memset(sumTimes.begin(), 0, sumTimes.count() * sizeof(double));
  110. int count = 0;
  111. double totalTime = 0;
  112. int totalCount = 0;
  113. do {
  114. int startY = SkScalarTruncToInt(rect.fBottom);
  115. double inc = 0;
  116. for (int timer = 0; timer < fTimers.count(); ++timer) {
  117. int height = (int)(fTimers[timer].fTimes[i] * kPixelPerMS + 0.5);
  118. int endY = SkTMax(startY - height, kDisplayPadding + kTextHeight);
  119. paint.setColor(fTimers[timer].fColor);
  120. canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
  121. SkIntToScalar(x), SkIntToScalar(endY), paint);
  122. startY = endY;
  123. inc += fTimers[timer].fTimes[i];
  124. sumTimes[timer] += fTimers[timer].fTimes[i];
  125. }
  126. int height = (int)(fTotalTimes[i] * kPixelPerMS + 0.5);
  127. height = SkTMax(0, height - (SkScalarTruncToInt(rect.fBottom) - startY));
  128. int endY = SkTMax(startY - height, kDisplayPadding + kTextHeight);
  129. paint.setColor(SK_ColorWHITE);
  130. canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
  131. SkIntToScalar(x), SkIntToScalar(endY), paint);
  132. totalTime += fTotalTimes[i];
  133. if (fTotalTimes[i] > 0) {
  134. ++totalCount;
  135. }
  136. if (inc > 0) {
  137. ++count;
  138. }
  139. i++;
  140. i &= (kMeasurementCount - 1); // fast mod
  141. x += xStep;
  142. } while (i != nextMeasurement);
  143. SkFont font(nullptr, 16);
  144. paint.setColor(SK_ColorWHITE);
  145. double time = totalTime / SkTMax(1, totalCount);
  146. double measure = fCumulativeMeasurementTime / SkTMax(1, fCumulativeMeasurementCount);
  147. canvas->drawString(SkStringPrintf("%4.3f ms -> %4.3f ms", time, measure),
  148. rect.fLeft + 3, rect.fTop + 14, font, paint);
  149. for (int timer = 0; timer < fTimers.count(); ++timer) {
  150. paint.setColor(fTimers[timer].fLabelColor);
  151. canvas->drawString(SkStringPrintf("%s: %4.3f ms", fTimers[timer].fLabel.c_str(),
  152. sumTimes[timer] / SkTMax(1, count)),
  153. rect.fLeft + 3, rect.fTop + 28 + (14 * timer), font, paint);
  154. }
  155. canvas->restore();
  156. }