OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/heads_up_display_layer_impl.h" | 5 #include "cc/heads_up_display_layer_impl.h" |
6 | 6 |
| 7 #include <limits> |
| 8 |
7 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
8 #include "cc/debug_rect_history.h" | 10 #include "cc/debug_rect_history.h" |
9 #include "cc/font_atlas.h" | 11 #include "cc/font_atlas.h" |
10 #include "cc/frame_rate_counter.h" | 12 #include "cc/frame_rate_counter.h" |
11 #include "cc/layer_tree_host_impl.h" | 13 #include "cc/layer_tree_host_impl.h" |
12 #include "cc/quad_sink.h" | 14 #include "cc/quad_sink.h" |
13 #include "cc/texture_draw_quad.h" | 15 #include "cc/texture_draw_quad.h" |
14 #include "skia/ext/platform_canvas.h" | 16 #include "skia/ext/platform_canvas.h" |
15 #include "skia/ext/platform_canvas.h" | 17 #include "skia/ext/platform_canvas.h" |
16 #include "third_party/khronos/GLES2/gl2.h" | 18 #include "third_party/khronos/GLES2/gl2.h" |
(...skipping 13 matching lines...) Expand all Loading... |
30 SkColorMatrix swizzleMatrix; | 32 SkColorMatrix swizzleMatrix; |
31 for (int i = 0; i < 20; ++i) | 33 for (int i = 0; i < 20; ++i) |
32 swizzleMatrix.fMat[i] = 0; | 34 swizzleMatrix.fMat[i] = 0; |
33 swizzleMatrix.fMat[0 + 5 * 2] = 1; | 35 swizzleMatrix.fMat[0 + 5 * 2] = 1; |
34 swizzleMatrix.fMat[1 + 5 * 1] = 1; | 36 swizzleMatrix.fMat[1 + 5 * 1] = 1; |
35 swizzleMatrix.fMat[2 + 5 * 0] = 1; | 37 swizzleMatrix.fMat[2 + 5 * 0] = 1; |
36 swizzleMatrix.fMat[3 + 5 * 3] = 1; | 38 swizzleMatrix.fMat[3 + 5 * 3] = 1; |
37 | 39 |
38 SkPaint paint; | 40 SkPaint paint; |
39 paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); | 41 paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); |
| 42 |
40 return paint; | 43 return paint; |
41 } | 44 } |
42 | 45 |
43 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(int id) | 46 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(int id) |
44 : LayerImpl(id) | 47 : LayerImpl(id) |
45 , m_averageFPS(0) | 48 , m_averageFPS(0) |
46 , m_stdDeviation(0) | 49 , m_minFPS(0) |
| 50 , m_maxFPS(0) |
47 , m_showFPSCounter(false) | 51 , m_showFPSCounter(false) |
48 { | 52 { |
49 } | 53 } |
50 | 54 |
51 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() | 55 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() |
52 { | 56 { |
53 } | 57 } |
54 | 58 |
55 void HeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr<FontAtlas> fontAtlas) | 59 void HeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr<FontAtlas> fontAtlas) |
56 { | 60 { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); | 163 std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); |
160 m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, pl
atformLayerTreeTop), bounds()); | 164 m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, pl
atformLayerTreeTop), bounds()); |
161 } | 165 } |
162 | 166 |
163 if (settings.showDebugRects()) | 167 if (settings.showDebugRects()) |
164 drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); | 168 drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); |
165 } | 169 } |
166 | 170 |
167 int HeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, FrameRateCounter*
fpsCounter) | 171 int HeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, FrameRateCounter*
fpsCounter) |
168 { | 172 { |
169 const int left = 2; | |
170 const int top = 2; | |
171 | |
172 const int padding = 4; | 173 const int padding = 4; |
| 174 const int gap = 6; |
173 | 175 |
174 const int fontHeight = m_fontAtlas.get() ? m_fontAtlas->fontHeight() : 0; | 176 const int fontHeight = m_fontAtlas.get() ? m_fontAtlas->fontHeight() : 0; |
175 const int graphWidth = fpsCounter->timeStampHistorySize() - 3; | 177 |
| 178 const int graphWidth = 120; |
176 const int graphHeight = 40; | 179 const int graphHeight = 40; |
177 | 180 |
178 const int width = graphWidth + 2 * padding; | 181 const int histogramWidth = 37; |
| 182 |
| 183 const int width = graphWidth + histogramWidth + 4 * padding; |
179 const int height = fontHeight + graphHeight + 4 * padding + 2; | 184 const int height = fontHeight + graphHeight + 4 * padding + 2; |
180 | 185 |
| 186 const int left = bounds().width() - width - 2; |
| 187 const int top = 2; |
| 188 |
181 SkPaint paint = createPaint(); | 189 SkPaint paint = createPaint(); |
182 | 190 |
183 // Draw background. | 191 // Draw background. |
184 paint.setColor(SkColorSetARGB(215, 17, 17, 17)); | 192 paint.setColor(SkColorSetARGB(215, 17, 17, 17)); |
185 canvas->drawRect(SkRect::MakeXYWH(left, top, width, height), paint); | 193 canvas->drawRect(SkRect::MakeXYWH(left, top, width, height), paint); |
186 | 194 |
187 SkRect textBounds = SkRect::MakeXYWH(left + padding, top + padding, graphWid
th, fontHeight); | 195 SkRect textBounds = SkRect::MakeXYWH(left + padding, top + padding, graphWid
th + histogramWidth + gap + 2, fontHeight); |
188 SkRect graphBounds = SkRect::MakeXYWH(left + padding, textBounds.bottom() +
2 * padding, graphWidth, graphHeight); | 196 SkRect graphBounds = SkRect::MakeXYWH(left + padding, textBounds.bottom() +
2 * padding, graphWidth, graphHeight); |
| 197 SkRect histogramBounds = SkRect::MakeXYWH(graphBounds.right() + gap, graphBo
unds.top(), histogramWidth, graphHeight); |
189 | 198 |
190 drawFPSCounterText(canvas, paint, fpsCounter, textBounds); | 199 drawFPSCounterText(canvas, paint, fpsCounter, textBounds); |
191 drawFPSCounterGraph(canvas, paint, fpsCounter, graphBounds); | 200 drawFPSCounterGraphAndHistogram(canvas, paint, fpsCounter, graphBounds, hist
ogramBounds); |
192 | 201 |
193 return top + height; | 202 return top + height; |
194 } | 203 } |
195 | 204 |
196 void HeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, SkPaint& pain
t, FrameRateCounter* fpsCounter, SkRect bounds) | 205 void HeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, SkPaint& pain
t, FrameRateCounter* fpsCounter, SkRect bounds) |
197 { | 206 { |
198 // Update FPS text - not every frame so text is readable | 207 // Update FPS text - not every frame so text is readable |
199 if (base::TimeDelta(fpsCounter->timeStampOfRecentFrame(0) - textUpdateTime).
InSecondsF() > 0.25) { | 208 if (base::TimeDelta(fpsCounter->timeStampOfRecentFrame(0) - textUpdateTime).
InSecondsF() > 0.25) { |
200 fpsCounter->getAverageFPSAndStandardDeviation(m_averageFPS, m_stdDeviati
on); | 209 m_averageFPS = fpsCounter->getAverageFPS(); |
201 textUpdateTime = fpsCounter->timeStampOfRecentFrame(0); | 210 textUpdateTime = fpsCounter->timeStampOfRecentFrame(0); |
202 } | 211 } |
203 | 212 |
204 // Draw FPS text. | 213 // Draw FPS text. |
205 if (m_fontAtlas.get()) { | 214 if (m_fontAtlas.get()) { |
206 std::string fpsText = base::StringPrintf("FPS:%5.1f", m_averageFPS); | 215 std::string fpsText = base::StringPrintf("FPS:%5.1f", m_averageFPS); |
207 std::string deviationText = base::StringPrintf("+/-%4.1f", m_stdDeviatio
n); | 216 std::string minMaxText = base::StringPrintf("%.0f-%.0f", std::min( m_min
FPS, m_maxFPS), m_maxFPS); |
208 | 217 |
209 int deviationWidth = m_fontAtlas->textSize(deviationText).width(); | 218 int minMaxWidth = m_fontAtlas->textSize(minMaxText).width(); |
210 gfx::Size textArea(bounds.width(), bounds.height()); | 219 gfx::Size textArea(bounds.width(), bounds.height()); |
211 | 220 |
212 paint.setColor(SK_ColorRED); | 221 paint.setColor(SK_ColorRED); |
213 m_fontAtlas->drawText(canvas, paint, fpsText, gfx::Point(bounds.left(),
bounds.top()), textArea); | 222 m_fontAtlas->drawText(canvas, paint, fpsText, gfx::Point(bounds.left(),
bounds.top()), textArea); |
214 m_fontAtlas->drawText(canvas, paint, deviationText, gfx::Point(bounds.ri
ght() - deviationWidth, bounds.top()), textArea); | 223 m_fontAtlas->drawText(canvas, paint, minMaxText, gfx::Point(bounds.right
() - minMaxWidth, bounds.top()), textArea); |
215 } | 224 } |
216 } | 225 } |
217 | 226 |
218 void HeadsUpDisplayLayerImpl::drawFPSCounterGraph(SkCanvas* canvas, SkPaint& pai
nt, FrameRateCounter* fpsCounter, SkRect bounds) | 227 void HeadsUpDisplayLayerImpl::drawFPSCounterGraphAndHistogram(SkCanvas* canvas,
SkPaint& paint, FrameRateCounter* fpsCounter, SkRect graphBounds, SkRect histogr
amBounds) |
219 { | 228 { |
220 const double loFPS = 0; | 229 const double loFPS = 0; |
221 const double hiFPS = 80; | 230 const double hiFPS = std::max(m_maxFPS + 10.0, 80.0); |
222 | |
223 paint.setStyle(SkPaint::kStroke_Style); | |
224 paint.setStrokeWidth(1); | |
225 | 231 |
226 // Draw top and bottom line. | 232 // Draw top and bottom line. |
227 paint.setColor(SkColorSetRGB(150, 150, 150)); | 233 paint.setColor(SkColorSetRGB(130, 130, 130)); |
228 canvas->drawLine(bounds.left(), bounds.top() - 1, bounds.right(), bounds.top
() - 1, paint); | 234 canvas->drawLine(graphBounds.left(), graphBounds.top() - 1, graphBounds.righ
t(), graphBounds.top() - 1, paint); |
229 canvas->drawLine(bounds.left(), bounds.bottom(), bounds.right(), bounds.bott
om(), paint); | 235 canvas->drawLine(graphBounds.left(), graphBounds.bottom(), graphBounds.right
(), graphBounds.bottom(), paint); |
230 | 236 |
231 // Draw 60fps line. | 237 // Draw 60fps line. |
| 238 const double top60 = graphBounds.top() + graphBounds.height() * (1 - ((60 -
loFPS) / (hiFPS - loFPS))) - 1; |
232 paint.setColor(SkColorSetRGB(100, 100, 100)); | 239 paint.setColor(SkColorSetRGB(100, 100, 100)); |
233 canvas->drawLine(bounds.left(), bounds.top() + bounds.height() / 4, bounds.r
ight(), bounds.top() + bounds.height() / 4, paint); | 240 canvas->drawLine(graphBounds.left(), top60, graphBounds.right(), top60, pain
t); |
234 | 241 |
235 // Draw FPS graph. | 242 // Collect graph and histogram data. |
236 int x = 0; | 243 double x = 0; |
| 244 const double timeScale = 60; // in pixels/second |
237 SkPath path; | 245 SkPath path; |
238 | 246 |
239 for (int i = 1; i < fpsCounter->timeStampHistorySize() - 1; ++i) { | 247 m_minFPS = std::numeric_limits<double>::max(); |
| 248 m_maxFPS = 0; |
| 249 |
| 250 const int histogramSize = 20; |
| 251 double histogram[histogramSize] = {0}; |
| 252 double maxBucketValue = 0; |
| 253 |
| 254 for (int i = fpsCounter->timeStampHistorySize() - 2; i > 0 && x <= graphBoun
ds.width(); --i) { |
240 base::TimeDelta delta = fpsCounter->timeStampOfRecentFrame(i + 1) - fpsC
ounter->timeStampOfRecentFrame(i); | 255 base::TimeDelta delta = fpsCounter->timeStampOfRecentFrame(i + 1) - fpsC
ounter->timeStampOfRecentFrame(i); |
241 | 256 |
242 // Skip plotting this particular instantaneous frame rate if it is not l
ikely to have been valid. | 257 // Skip this particular instantaneous frame rate if it is not likely to
have been valid. |
243 if (!fpsCounter->isBadFrameInterval(delta)) { | 258 if (!fpsCounter->isBadFrameInterval(delta)) { |
| 259 |
244 double fps = 1.0 / delta.InSecondsF(); | 260 double fps = 1.0 / delta.InSecondsF(); |
245 | 261 |
| 262 m_minFPS = std::min(fps, m_minFPS); |
| 263 m_maxFPS = std::max(fps, m_maxFPS); |
| 264 |
246 // Clamp the FPS to the range we want to plot visually. | 265 // Clamp the FPS to the range we want to plot visually. |
247 double p = 1 - ((fps - loFPS) / (hiFPS - loFPS)); | 266 double p = (fps - loFPS) / (hiFPS - loFPS); |
248 if (p < 0) | 267 if (p < 0) |
249 p = 0; | 268 p = 0; |
250 if (p > 1) | 269 if (p > 1) |
251 p = 1; | 270 p = 1; |
252 | 271 |
253 // Plot this data point. | 272 // Plot this data point. |
254 SkPoint cur = SkPoint::Make(bounds.left() + x, bounds.top() + p * bo
unds.height()); | 273 SkPoint cur = SkPoint::Make(graphBounds.right() - x, graphBounds.bot
tom() - p * graphBounds.height()); |
255 if (path.isEmpty()) | 274 if (path.isEmpty()) |
256 path.moveTo(cur); | 275 path.moveTo(cur); |
257 else | 276 else |
258 path.lineTo(cur); | 277 path.lineTo(cur); |
| 278 |
| 279 // Use the fps value to find the right bucket in the histogram. |
| 280 int bucketIndex = floor(p * (histogramSize - 1)); |
| 281 |
| 282 // Add the delta time to take the time spent at that fps rate into a
ccount. |
| 283 histogram[bucketIndex] += delta.InSecondsF(); |
| 284 maxBucketValue = std::max(histogram[bucketIndex], maxBucketValue); |
259 } | 285 } |
260 | 286 |
261 x += 1; | 287 x += delta.InSecondsF() * timeScale; |
262 } | 288 } |
263 | 289 |
| 290 // Draw FPS histogram. |
| 291 paint.setColor(SkColorSetRGB(130, 130, 130)); |
| 292 canvas->drawLine(histogramBounds.left() - 1, histogramBounds.top() - 1, hist
ogramBounds.left() - 1, histogramBounds.bottom() + 1, paint); |
| 293 canvas->drawLine(histogramBounds.right() + 1, histogramBounds.top() - 1, his
togramBounds.right() + 1, histogramBounds.bottom() + 1, paint); |
| 294 |
| 295 paint.setColor(SK_ColorRED); |
| 296 const double barHeight = histogramBounds.height() / histogramSize; |
| 297 |
| 298 for (int i = histogramSize - 1; i >= 0; --i) { |
| 299 if (histogram[i] > 0) { |
| 300 double barWidth = histogram[i] / maxBucketValue * histogramBounds.wi
dth(); |
| 301 canvas->drawRect(SkRect::MakeXYWH(histogramBounds.left(), histogramB
ounds.bottom() - (i + 1) * barHeight, barWidth, 1), paint); |
| 302 } |
| 303 } |
| 304 |
| 305 // Draw FPS graph. |
264 paint.setAntiAlias(true); | 306 paint.setAntiAlias(true); |
265 paint.setColor(SK_ColorRED); | 307 paint.setStyle(SkPaint::kStroke_Style); |
| 308 paint.setStrokeWidth(1); |
| 309 |
266 canvas->drawPath(path, paint); | 310 canvas->drawPath(path, paint); |
267 } | 311 } |
268 | 312 |
269 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, DebugRectHistory*
debugRectHistory) | 313 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, DebugRectHistory*
debugRectHistory) |
270 { | 314 { |
271 const std::vector<DebugRect>& debugRects = debugRectHistory->debugRects(); | 315 const std::vector<DebugRect>& debugRects = debugRectHistory->debugRects(); |
272 | 316 |
273 for (size_t i = 0; i < debugRects.size(); ++i) { | 317 for (size_t i = 0; i < debugRects.size(); ++i) { |
274 SkColor strokeColor = 0; | 318 SkColor strokeColor = 0; |
275 SkColor fillColor = 0; | 319 SkColor fillColor = 0; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 canvas->drawRect(skRect, paint); | 363 canvas->drawRect(skRect, paint); |
320 } | 364 } |
321 } | 365 } |
322 | 366 |
323 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const | 367 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const |
324 { | 368 { |
325 return "HeadsUpDisplayLayer"; | 369 return "HeadsUpDisplayLayer"; |
326 } | 370 } |
327 | 371 |
328 } // namespace cc | 372 } // namespace cc |
OLD | NEW |