| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 The Chromium 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 "config.h" | |
| 6 | |
| 7 #if USE(ACCELERATED_COMPOSITING) | |
| 8 #include "CCFrameRateCounter.h" | |
| 9 | |
| 10 #include <cmath> | |
| 11 | |
| 12 #include "CCProxy.h" | |
| 13 #include <public/Platform.h> | |
| 14 #include <wtf/CurrentTime.h> | |
| 15 | |
| 16 namespace cc { | |
| 17 | |
| 18 const double CCFrameRateCounter::kFrameTooFast = 1.0 / 70.0; // measured in seco
nds | |
| 19 const double CCFrameRateCounter::kFrameTooSlow = 1.0 / 12.0; | |
| 20 const double CCFrameRateCounter::kDroppedFrameTime = 1.0 / 50.0; | |
| 21 | |
| 22 // safeMod works on -1, returning m-1 in that case. | |
| 23 static inline int safeMod(int number, int modulus) | |
| 24 { | |
| 25 return (number + modulus) % modulus; | |
| 26 } | |
| 27 | |
| 28 inline double CCFrameRateCounter::frameInterval(int frameNumber) const | |
| 29 { | |
| 30 return m_timeStampHistory[frameIndex(frameNumber)] - | |
| 31 m_timeStampHistory[frameIndex(frameNumber - 1)]; | |
| 32 } | |
| 33 | |
| 34 inline int CCFrameRateCounter::frameIndex(int frameNumber) const | |
| 35 { | |
| 36 return safeMod(frameNumber, kTimeStampHistorySize); | |
| 37 } | |
| 38 | |
| 39 CCFrameRateCounter::CCFrameRateCounter() | |
| 40 : m_currentFrameNumber(1) | |
| 41 , m_droppedFrameCount(0) | |
| 42 { | |
| 43 m_timeStampHistory[0] = currentTime(); | |
| 44 m_timeStampHistory[1] = m_timeStampHistory[0]; | |
| 45 for (int i = 2; i < kTimeStampHistorySize; i++) | |
| 46 m_timeStampHistory[i] = 0; | |
| 47 } | |
| 48 | |
| 49 void CCFrameRateCounter::markBeginningOfFrame(double timestamp) | |
| 50 { | |
| 51 m_timeStampHistory[frameIndex(m_currentFrameNumber)] = timestamp; | |
| 52 double frameIntervalSeconds = frameInterval(m_currentFrameNumber); | |
| 53 | |
| 54 if (CCProxy::hasImplThread() && m_currentFrameNumber > 0) { | |
| 55 double drawDelayMs = frameIntervalSeconds * 1000.0; | |
| 56 WebKit::Platform::current()->histogramCustomCounts("Renderer4.Compositor
ThreadImplDrawDelay", static_cast<int>(drawDelayMs), 1, 120, 60); | |
| 57 } | |
| 58 | |
| 59 if (!isBadFrameInterval(frameIntervalSeconds) && frameIntervalSeconds > kDro
ppedFrameTime) | |
| 60 ++m_droppedFrameCount; | |
| 61 } | |
| 62 | |
| 63 void CCFrameRateCounter::markEndOfFrame() | |
| 64 { | |
| 65 m_currentFrameNumber += 1; | |
| 66 } | |
| 67 | |
| 68 bool CCFrameRateCounter::isBadFrameInterval(double intervalBetweenConsecutiveFra
mes) const | |
| 69 { | |
| 70 bool schedulerAllowsDoubleFrames = !CCProxy::hasImplThread(); | |
| 71 bool intervalTooFast = schedulerAllowsDoubleFrames && intervalBetweenConsecu
tiveFrames < kFrameTooFast; | |
| 72 bool intervalTooSlow = intervalBetweenConsecutiveFrames > kFrameTooSlow; | |
| 73 return intervalTooFast || intervalTooSlow; | |
| 74 } | |
| 75 | |
| 76 bool CCFrameRateCounter::isBadFrame(int frameNumber) const | |
| 77 { | |
| 78 return isBadFrameInterval(frameInterval(frameNumber)); | |
| 79 } | |
| 80 | |
| 81 void CCFrameRateCounter::getAverageFPSAndStandardDeviation(double& averageFPS, d
ouble& standardDeviation) const | |
| 82 { | |
| 83 int frame = m_currentFrameNumber - 1; | |
| 84 averageFPS = 0; | |
| 85 int averageFPSCount = 0; | |
| 86 double fpsVarianceNumerator = 0; | |
| 87 | |
| 88 // Walk backwards through the samples looking for a run of good frame | |
| 89 // timings from which to compute the mean and standard deviation. | |
| 90 // | |
| 91 // Slow frames occur just because the user is inactive, and should be | |
| 92 // ignored. Fast frames are ignored if the scheduler is in single-thread | |
| 93 // mode in order to represent the true frame rate in spite of the fact that | |
| 94 // the first few swapbuffers happen instantly which skews the statistics | |
| 95 // too much for short lived animations. | |
| 96 // | |
| 97 // isBadFrame encapsulates the frame too slow/frame too fast logic. | |
| 98 while (1) { | |
| 99 if (!isBadFrame(frame)) { | |
| 100 averageFPSCount++; | |
| 101 double secForLastFrame = m_timeStampHistory[frameIndex(frame)] - | |
| 102 m_timeStampHistory[frameIndex(frame - 1)]; | |
| 103 double x = 1.0 / secForLastFrame; | |
| 104 double deltaFromAverage = x - averageFPS; | |
| 105 // Change with caution - numerics. http://en.wikipedia.org/wiki/Stan
dard_deviation | |
| 106 averageFPS = averageFPS + deltaFromAverage / averageFPSCount; | |
| 107 fpsVarianceNumerator = fpsVarianceNumerator + deltaFromAverage * (x
- averageFPS); | |
| 108 } | |
| 109 if (averageFPSCount && isBadFrame(frame)) { | |
| 110 // We've gathered a run of good samples, so stop. | |
| 111 break; | |
| 112 } | |
| 113 --frame; | |
| 114 if (frameIndex(frame) == frameIndex(m_currentFrameNumber) || frame < 0)
{ | |
| 115 // We've gone through all available historical data, so stop. | |
| 116 break; | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 standardDeviation = sqrt(fpsVarianceNumerator / averageFPSCount); | |
| 121 } | |
| 122 | |
| 123 double CCFrameRateCounter::timeStampOfRecentFrame(int n) | |
| 124 { | |
| 125 ASSERT(n >= 0 && n < kTimeStampHistorySize); | |
| 126 int desiredIndex = (frameIndex(m_currentFrameNumber) + n) % kTimeStampHistor
ySize; | |
| 127 return m_timeStampHistory[desiredIndex]; | |
| 128 } | |
| 129 | |
| 130 } // namespace cc | |
| 131 | |
| 132 #endif // USE(ACCELERATED_COMPOSITING) | |
| OLD | NEW |