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 |