| 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 "config.h" | 5 #include "config.h" |
| 6 | 6 |
| 7 #include "cc/heads_up_display_layer_impl.h" | 7 #include "cc/heads_up_display_layer_impl.h" |
| 8 | 8 |
| 9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
| 10 #include "cc/debug_rect_history.h" | 10 #include "cc/debug_rect_history.h" |
| 11 #include "cc/font_atlas.h" | 11 #include "cc/font_atlas.h" |
| 12 #include "cc/frame_rate_counter.h" | 12 #include "cc/frame_rate_counter.h" |
| 13 #include "cc/layer_tree_host_impl.h" | 13 #include "cc/layer_tree_host_impl.h" |
| 14 #include "cc/quad_sink.h" | 14 #include "cc/quad_sink.h" |
| 15 #include "cc/texture_draw_quad.h" | 15 #include "cc/texture_draw_quad.h" |
| 16 #include "skia/ext/platform_canvas.h" | 16 #include "skia/ext/platform_canvas.h" |
| 17 #include "skia/ext/platform_canvas.h" | 17 #include "skia/ext/platform_canvas.h" |
| 18 #include "third_party/khronos/GLES2/gl2.h" | 18 #include "third_party/khronos/GLES2/gl2.h" |
| 19 #include "third_party/khronos/GLES2/gl2ext.h" | 19 #include "third_party/khronos/GLES2/gl2ext.h" |
| 20 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" |
| 21 #include "third_party/skia/include/core/SkPaint.h" | 21 #include "third_party/skia/include/core/SkPaint.h" |
| 22 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" | 22 #include "third_party/skia/include/effects/SkColorMatrixFilter.h" |
| 23 #include "ui/gfx/point.h" | 23 #include "ui/gfx/point.h" |
| 24 #include "ui/gfx/size.h" |
| 24 | 25 |
| 25 namespace cc { | 26 namespace cc { |
| 26 | 27 |
| 27 static inline SkPaint createPaint() | 28 static inline SkPaint createPaint() |
| 28 { | 29 { |
| 29 // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to | 30 // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to |
| 30 // swizzle our colors when drawing to the SkCanvas. | 31 // swizzle our colors when drawing to the SkCanvas. |
| 31 SkColorMatrix swizzleMatrix; | 32 SkColorMatrix swizzleMatrix; |
| 32 for (int i = 0; i < 20; ++i) | 33 for (int i = 0; i < 20; ++i) |
| 33 swizzleMatrix.fMat[i] = 0; | 34 swizzleMatrix.fMat[i] = 0; |
| 34 swizzleMatrix.fMat[0 + 5 * 2] = 1; | 35 swizzleMatrix.fMat[0 + 5 * 2] = 1; |
| 35 swizzleMatrix.fMat[1 + 5 * 1] = 1; | 36 swizzleMatrix.fMat[1 + 5 * 1] = 1; |
| 36 swizzleMatrix.fMat[2 + 5 * 0] = 1; | 37 swizzleMatrix.fMat[2 + 5 * 0] = 1; |
| 37 swizzleMatrix.fMat[3 + 5 * 3] = 1; | 38 swizzleMatrix.fMat[3 + 5 * 3] = 1; |
| 38 | 39 |
| 39 SkPaint paint; | 40 SkPaint paint; |
| 40 paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); | 41 paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref(); |
| 41 return paint; | 42 return paint; |
| 42 } | 43 } |
| 43 | 44 |
| 44 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(int id) | 45 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(int id) |
| 45 : LayerImpl(id) | 46 : LayerImpl(id) |
| 47 , m_averageFPS(0) |
| 48 , m_stdDeviation(0) |
| 46 { | 49 { |
| 47 } | 50 } |
| 48 | 51 |
| 49 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() | 52 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() |
| 50 { | 53 { |
| 51 } | 54 } |
| 52 | 55 |
| 53 void HeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr<FontAtlas> fontAtlas) | 56 void HeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr<FontAtlas> fontAtlas) |
| 54 { | 57 { |
| 55 m_fontAtlas = fontAtlas.Pass(); | 58 m_fontAtlas = fontAtlas.Pass(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 void HeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas) | 139 void HeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas) |
| 137 { | 140 { |
| 138 const LayerTreeSettings& settings = layerTreeHostImpl()->settings(); | 141 const LayerTreeSettings& settings = layerTreeHostImpl()->settings(); |
| 139 | 142 |
| 140 if (settings.showPlatformLayerTree) { | 143 if (settings.showPlatformLayerTree) { |
| 141 SkPaint paint = createPaint(); | 144 SkPaint paint = createPaint(); |
| 142 paint.setColor(SkColorSetARGB(192, 0, 0, 0)); | 145 paint.setColor(SkColorSetARGB(192, 0, 0, 0)); |
| 143 canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().heigh
t()), paint); | 146 canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().heigh
t()), paint); |
| 144 } | 147 } |
| 145 | 148 |
| 146 int fpsCounterHeight = 40; | 149 int platformLayerTreeTop = 0; |
| 147 int fpsCounterTop = 2; | |
| 148 int platformLayerTreeTop; | |
| 149 | 150 |
| 150 if (settings.showFPSCounter) | 151 if (settings.showFPSCounter) |
| 151 platformLayerTreeTop = fpsCounterTop + fpsCounterHeight; | 152 platformLayerTreeTop = drawFPSCounter(canvas, layerTreeHostImpl()->fpsCo
unter()); |
| 152 else | |
| 153 platformLayerTreeTop = 0; | |
| 154 | |
| 155 if (settings.showFPSCounter) | |
| 156 drawFPSCounter(canvas, layerTreeHostImpl()->fpsCounter(), fpsCounterTop,
fpsCounterHeight); | |
| 157 | 153 |
| 158 if (settings.showPlatformLayerTree && m_fontAtlas.get()) { | 154 if (settings.showPlatformLayerTree && m_fontAtlas.get()) { |
| 159 std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); | 155 std::string layerTree = layerTreeHostImpl()->layerTreeAsText(); |
| 160 m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, pl
atformLayerTreeTop), bounds()); | 156 m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, pl
atformLayerTreeTop), bounds()); |
| 161 } | 157 } |
| 162 | 158 |
| 163 if (settings.showDebugRects()) | 159 if (settings.showDebugRects()) |
| 164 drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); | 160 drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory()); |
| 165 } | 161 } |
| 166 | 162 |
| 167 void HeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, FrameRateCounter*
fpsCounter, int top, int height) | 163 int HeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, FrameRateCounter*
fpsCounter) |
| 168 { | 164 { |
| 169 float textWidth = 170; // so text fits on linux. | 165 const int left = 2; |
| 170 float graphWidth = fpsCounter->timeStampHistorySize(); | 166 const int top = 2; |
| 171 | 167 |
| 172 // Draw the FPS text. | 168 const int padding = 4; |
| 173 drawFPSCounterText(canvas, fpsCounter, top, textWidth, height); | 169 |
| 170 const int fontHeight = m_fontAtlas.get() ? m_fontAtlas->fontHeight() : 0; |
| 171 const int graphWidth = fpsCounter->timeStampHistorySize() - 3; |
| 172 const int graphHeight = 40; |
| 173 |
| 174 const int width = graphWidth + 2 * padding; |
| 175 const int height = fontHeight + graphHeight + 4 * padding + 2; |
| 176 |
| 177 SkPaint paint = createPaint(); |
| 178 |
| 179 // Draw background. |
| 180 paint.setColor(SkColorSetARGB(215, 17, 17, 17)); |
| 181 canvas->drawRect(SkRect::MakeXYWH(left, top, width, height), paint); |
| 182 |
| 183 SkRect textBounds = SkRect::MakeXYWH(left + padding, top + padding, graphWid
th, fontHeight); |
| 184 SkRect graphBounds = SkRect::MakeXYWH(left + padding, textBounds.bottom() +
2 * padding, graphWidth, graphHeight); |
| 185 |
| 186 drawFPSCounterText(canvas, paint, fpsCounter, textBounds); |
| 187 drawFPSCounterGraph(canvas, paint, fpsCounter, graphBounds); |
| 188 |
| 189 return top + height; |
| 190 } |
| 191 |
| 192 void HeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, SkPaint& pain
t, FrameRateCounter* fpsCounter, SkRect bounds) |
| 193 { |
| 194 // Update FPS text - not every frame so text is readable |
| 195 if (base::TimeDelta(fpsCounter->timeStampOfRecentFrame(0) - textUpdateTime).
InSecondsF() > 0.25) { |
| 196 fpsCounter->getAverageFPSAndStandardDeviation(m_averageFPS, m_stdDeviati
on); |
| 197 textUpdateTime = fpsCounter->timeStampOfRecentFrame(0); |
| 198 } |
| 199 |
| 200 // Draw FPS text. |
| 201 if (m_fontAtlas.get()) { |
| 202 std::string fpsText = base::StringPrintf("FPS:%5.1f", m_averageFPS); |
| 203 std::string deviationText = base::StringPrintf("+/-%4.1f", m_stdDeviatio
n); |
| 204 |
| 205 int deviationWidth = m_fontAtlas->textSize(deviationText).width(); |
| 206 gfx::Size textArea(bounds.width(), bounds.height()); |
| 207 |
| 208 paint.setColor(SK_ColorRED); |
| 209 m_fontAtlas->drawText(canvas, paint, fpsText, gfx::Point(bounds.left(),
bounds.top()), textArea); |
| 210 m_fontAtlas->drawText(canvas, paint, deviationText, gfx::Point(bounds.ri
ght() - deviationWidth, bounds.top()), textArea); |
| 211 } |
| 212 } |
| 213 |
| 214 void HeadsUpDisplayLayerImpl::drawFPSCounterGraph(SkCanvas* canvas, SkPaint& pai
nt, FrameRateCounter* fpsCounter, SkRect bounds) |
| 215 { |
| 216 const double loFPS = 0; |
| 217 const double hiFPS = 80; |
| 218 |
| 219 paint.setStyle(SkPaint::kStroke_Style); |
| 220 paint.setStrokeWidth(1); |
| 221 |
| 222 // Draw top and bottom line. |
| 223 paint.setColor(SkColorSetRGB(150, 150, 150)); |
| 224 canvas->drawLine(bounds.left(), bounds.top() - 1, bounds.right(), bounds.top
() - 1, paint); |
| 225 canvas->drawLine(bounds.left(), bounds.bottom(), bounds.right(), bounds.bott
om(), paint); |
| 226 |
| 227 // Draw 60fps line. |
| 228 paint.setColor(SkColorSetRGB(100, 100, 100)); |
| 229 canvas->drawLine(bounds.left(), bounds.top() + bounds.height() / 4, bounds.r
ight(), bounds.top() + bounds.height() / 4, paint); |
| 174 | 230 |
| 175 // Draw FPS graph. | 231 // Draw FPS graph. |
| 176 const double loFPS = 0; | 232 int x = 0; |
| 177 const double hiFPS = 80; | 233 SkPath path; |
| 178 SkPaint paint = createPaint(); | |
| 179 paint.setColor(SkColorSetRGB(154, 205, 50)); | |
| 180 canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top, graphWidth, height / 2
), paint); | |
| 181 | 234 |
| 182 paint.setColor(SkColorSetRGB(255, 250, 205)); | 235 for (int i = 1; i < fpsCounter->timeStampHistorySize() - 1; ++i) { |
| 183 canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top + height / 2, graphWidt
h, height / 2), paint); | 236 base::TimeDelta delta = fpsCounter->timeStampOfRecentFrame(i + 1) - fpsC
ounter->timeStampOfRecentFrame(i); |
| 184 | |
| 185 int graphLeft = static_cast<int>(textWidth + 3); | |
| 186 int x = 0; | |
| 187 double h = static_cast<double>(height - 2); | |
| 188 SkPath path; | |
| 189 for (int i = 0; i < fpsCounter->timeStampHistorySize() - 1; ++i) { | |
| 190 int j = i + 1; | |
| 191 base::TimeDelta delta = fpsCounter->timeStampOfRecentFrame(j) - fpsCount
er->timeStampOfRecentFrame(i); | |
| 192 | 237 |
| 193 // Skip plotting this particular instantaneous frame rate if it is not l
ikely to have been valid. | 238 // Skip plotting this particular instantaneous frame rate if it is not l
ikely to have been valid. |
| 194 if (fpsCounter->isBadFrameInterval(delta)) { | 239 if (!fpsCounter->isBadFrameInterval(delta)) { |
| 195 x += 1; | 240 double fps = 1.0 / delta.InSecondsF(); |
| 196 continue; | 241 |
| 242 // Clamp the FPS to the range we want to plot visually. |
| 243 double p = 1 - ((fps - loFPS) / (hiFPS - loFPS)); |
| 244 if (p < 0) |
| 245 p = 0; |
| 246 if (p > 1) |
| 247 p = 1; |
| 248 |
| 249 // Plot this data point. |
| 250 SkPoint cur = SkPoint::Make(bounds.left() + x, bounds.top() + p * bo
unds.height()); |
| 251 if (path.isEmpty()) |
| 252 path.moveTo(cur); |
| 253 else |
| 254 path.lineTo(cur); |
| 197 } | 255 } |
| 198 | 256 |
| 199 double fps = 1.0 / delta.InSecondsF(); | |
| 200 | |
| 201 // Clamp the FPS to the range we want to plot visually. | |
| 202 double p = 1 - ((fps - loFPS) / (hiFPS - loFPS)); | |
| 203 if (p < 0) | |
| 204 p = 0; | |
| 205 if (p > 1) | |
| 206 p = 1; | |
| 207 | |
| 208 // Plot this data point. | |
| 209 SkPoint cur = SkPoint::Make(graphLeft + x, 1 + top + p*h); | |
| 210 if (path.isEmpty()) | |
| 211 path.moveTo(cur); | |
| 212 else | |
| 213 path.lineTo(cur); | |
| 214 x += 1; | 257 x += 1; |
| 215 } | 258 } |
| 259 |
| 260 paint.setAntiAlias(true); |
| 216 paint.setColor(SK_ColorRED); | 261 paint.setColor(SK_ColorRED); |
| 217 paint.setStyle(SkPaint::kStroke_Style); | |
| 218 paint.setStrokeWidth(1); | |
| 219 paint.setAntiAlias(true); | |
| 220 canvas->drawPath(path, paint); | 262 canvas->drawPath(path, paint); |
| 221 } | 263 } |
| 222 | 264 |
| 223 void HeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, FrameRateCoun
ter* fpsCounter, int top, int width, int height) | |
| 224 { | |
| 225 double averageFPS, stdDeviation; | |
| 226 fpsCounter->getAverageFPSAndStandardDeviation(averageFPS, stdDeviation); | |
| 227 | |
| 228 // Draw background. | |
| 229 SkPaint paint = createPaint(); | |
| 230 paint.setColor(SK_ColorBLACK); | |
| 231 canvas->drawRect(SkRect::MakeXYWH(2, top, width, height), paint); | |
| 232 | |
| 233 // Draw FPS text. | |
| 234 if (m_fontAtlas.get()) | |
| 235 m_fontAtlas->drawText(canvas, createPaint(), base::StringPrintf("FPS: %4
.1f +/- %3.1f", averageFPS, stdDeviation), gfx::Point(10, height / 3), gfx::Size
(width, height)); | |
| 236 } | |
| 237 | |
| 238 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, DebugRectHistory*
debugRectHistory) | 265 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, DebugRectHistory*
debugRectHistory) |
| 239 { | 266 { |
| 240 const std::vector<DebugRect>& debugRects = debugRectHistory->debugRects(); | 267 const std::vector<DebugRect>& debugRects = debugRectHistory->debugRects(); |
| 241 | 268 |
| 242 for (size_t i = 0; i < debugRects.size(); ++i) { | 269 for (size_t i = 0; i < debugRects.size(); ++i) { |
| 243 SkColor strokeColor = 0; | 270 SkColor strokeColor = 0; |
| 244 SkColor fillColor = 0; | 271 SkColor fillColor = 0; |
| 245 | 272 |
| 246 switch (debugRects[i].type) { | 273 switch (debugRects[i].type) { |
| 247 case PaintRectType: | 274 case PaintRectType: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 canvas->drawRect(skRect, paint); | 315 canvas->drawRect(skRect, paint); |
| 289 } | 316 } |
| 290 } | 317 } |
| 291 | 318 |
| 292 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const | 319 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const |
| 293 { | 320 { |
| 294 return "HeadsUpDisplayLayer"; | 321 return "HeadsUpDisplayLayer"; |
| 295 } | 322 } |
| 296 | 323 |
| 297 } // namespace cc | 324 } // namespace cc |
| OLD | NEW |