12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/heads_up_display_layer_impl.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/debug_colors.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/debug_rect_history.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/frame_rate_counter.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/paint_time_counter.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/quad_sink.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/renderer.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/quads/texture_draw_quad.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/memory_history.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/layer_tree_impl.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/platform_canvas.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2ext.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkTypeface.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline SkPaint CreatePaint() {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if (SK_R32_SHIFT || SK_B32_SHIFT != 16)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // swizzle our colors when drawing to the SkCanvas.
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkColorMatrix swizzle_matrix;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < 20; ++i)
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    swizzle_matrix.fMat[i] = 0;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[0 + 5 * 2] = 1;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[1 + 5 * 1] = 1;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[2 + 5 * 0] = 1;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[3 + 5 * 3] = 1;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skia::RefPtr<SkColorMatrixFilter> filter =
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      skia::AdoptRef(new SkColorMatrixFilter(swizzle_matrix));
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColorFilter(filter.get());
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return paint;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value,
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      double start_upper_bound)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : value(0.0),
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      min(0.0),
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max(0.0),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_upper_bound(start_upper_bound),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default_upper_bound(start_upper_bound),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      indicator(indicator_value) {}
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double HeadsUpDisplayLayerImpl::Graph::UpdateUpperBound() {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double target_upper_bound = std::max(max, default_upper_bound);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_upper_bound += (target_upper_bound - current_upper_bound) * 0.5;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return current_upper_bound;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 int id)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : LayerImpl(tree_impl, id),
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      typeface_(skia::AdoptRef(
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SkTypeface::CreateFromName("monospace", SkTypeface::kBold))),
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fps_graph_(60.0, 80.0),
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_time_graph_(16.0, 48.0) {}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<LayerImpl> HeadsUpDisplayLayerImpl::CreateLayerImpl(
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerTreeImpl* tree_impl) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return HeadsUpDisplayLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode,
83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       ResourceProvider* resource_provider) {
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return false;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hud_resource_ = ScopedResource::create(resource_provider);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(danakj): The HUD could swap between two textures instead of creating a
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // texture every frame in ubercompositor.
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (hud_resource_->size() != content_bounds() ||
93ff02a5906993e65f5c8bf12b09245e7a673d8283boliu@chromium.org      (hud_resource_->id() &&
94ff02a5906993e65f5c8bf12b09245e7a673d8283boliu@chromium.org       resource_provider->InUseByConsumer(hud_resource_->id()))) {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hud_resource_->Free();
96ff02a5906993e65f5c8bf12b09245e7a673d8283boliu@chromium.org  }
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id()) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hud_resource_->Allocate(
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        content_bounds(), GL_RGBA, ResourceProvider::TextureUsageAny);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return LayerImpl::WillDraw(draw_mode, resource_provider);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::AppendQuads(QuadSink* quad_sink,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          AppendQuadsData* append_quads_data) {
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id())
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SharedQuadState* shared_quad_state =
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      quad_sink->UseSharedQuadState(CreateSharedQuadState());
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect quad_rect(content_bounds());
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool premultiplied_alpha = true;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF uv_top_left(0.f, 0.f);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF uv_bottom_right(1.f, 1.f);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const float vertex_opacity[] = { 1.f, 1.f, 1.f, 1.f };
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool flipped = false;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quad->SetNew(shared_quad_state,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               quad_rect,
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               opaque_rect,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               hud_resource_->id(),
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               premultiplied_alpha,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               uv_top_left,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               uv_bottom_right,
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               SK_ColorTRANSPARENT,
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               vertex_opacity,
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               flipped);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::UpdateHudTexture(
136ff02a5906993e65f5c8bf12b09245e7a673d8283boliu@chromium.org    DrawMode draw_mode,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResourceProvider* resource_provider) {
138ff02a5906993e65f5c8bf12b09245e7a673d8283boliu@chromium.org  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE || !hud_resource_->id())
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkISize canvas_size;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (hud_canvas_)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas_size = hud_canvas_->getDeviceSize();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas_size.set(0, 0);
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (canvas_size.width() != content_bounds().width() ||
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      canvas_size.width() != content_bounds().height() || !hud_canvas_) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool opaque = false;
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    hud_canvas_ = make_scoped_ptr(skia::CreateBitmapCanvas(
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        content_bounds().width(), content_bounds().height(), opaque));
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateHudContents();
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  hud_canvas_->save();
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  hud_canvas_->scale(contents_scale_x(), contents_scale_y());
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawHudContents(hud_canvas_.get());
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  hud_canvas_->restore();
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkBitmap* bitmap = &hud_canvas_->getDevice()->accessBitmap(false);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkAutoLockPixels locker(*bitmap);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  gfx::Rect content_rect(content_bounds());
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  resource_provider->SetPixels(hud_resource_->id(),
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               static_cast<const uint8_t*>(bitmap->getPixels()),
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                               content_rect,
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                               content_rect,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               gfx::Vector2d());
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DidLoseOutputSurface() { hud_resource_.reset(); }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HeadsUpDisplayLayerImpl::LayerIsAlwaysDamaged() const { return true; }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::UpdateHudContents() {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't update numbers every frame so text is readable.
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeTicks now = layer_tree_impl()->CurrentFrameTimeTicks();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (base::TimeDelta(now - time_of_last_graph_update_).InSecondsF() > 0.25f) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    time_of_last_graph_update_ = now;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.show_fps_counter) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter();
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fps_graph_.value = fps_counter->GetAverageFPS();
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.continuous_painting) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PaintTimeCounter* paint_time_counter =
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          layer_tree_impl()->paint_time_counter();
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta latest, min, max;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (paint_time_counter->End())
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        latest = **paint_time_counter->End();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_counter->GetMinAndMaxPaintTime(&min, &max);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.value = latest.InMillisecondsF();
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.min = min.InMillisecondsF();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.max = max.InMillisecondsF();
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.ShowMemoryStats()) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MemoryHistory* memory_history = layer_tree_impl()->memory_history();
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (memory_history->End())
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memory_entry_ = **memory_history->End();
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memory_entry_ = MemoryHistory::Entry();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fps_graph_.UpdateUpperBound();
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint_time_graph_.UpdateUpperBound();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) const {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.ShowHudRects())
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history());
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect area = SkRect::MakeEmpty();
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.continuous_painting) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    area = DrawPaintTimeDisplay(
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        canvas, layer_tree_impl()->paint_time_counter(), 0, 0);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (debug_state.show_fps_counter) {
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Don't show the FPS display when continuous painting is enabled, because
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // it would show misleading numbers.
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    area =
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.ShowMemoryStats())
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawMemoryDisplay(canvas, 0, area.bottom(), SkMaxScalar(area.width(), 150));
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint* paint,
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& text,
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint::Align align,
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int size,
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int x,
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int y) const {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool anti_alias = paint->isAntiAlias();
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setAntiAlias(true);
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTextSize(size);
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTextAlign(align);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTypeface(typeface_.get());
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawText(text.c_str(), text.length(), x, y, *paint);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setAntiAlias(anti_alias);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint* paint,
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& text,
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint::Align align,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int size,
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const SkPoint& pos) const {
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, paint, text, align, size, pos.x(), pos.y());
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawGraphBackground(SkCanvas* canvas,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  SkPaint* paint,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  const SkRect& bounds) const {
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDBackgroundColor());
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawRect(bounds, *paint);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawGraphLines(SkCanvas* canvas,
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             SkPaint* paint,
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const SkRect& bounds,
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const Graph& graph) const {
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw top and bottom line.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDSeparatorLineColor());
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(bounds.left(),
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() - 1,
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.right(),
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() - 1,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   *paint);
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.left(), bounds.bottom(), bounds.right(), bounds.bottom(), *paint);
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw indicator line (additive blend mode to increase contrast when drawn on
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // top of graph).
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDIndicatorLineColor());
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setXfermodeMode(SkXfermode::kPlus_Mode);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double indicator_top =
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) -
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1.0;
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(bounds.left(),
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() + indicator_top,
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.right(),
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() + indicator_top,
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   *paint);
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setXfermode(NULL);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FrameRateCounter* fps_counter,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top) const {
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGap = 6;
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 15;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphWidth = fps_counter->time_stamp_history_size() - 2;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphHeight = 40;
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kHistogramWidth = 37;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = kGraphWidth + kHistogramWidth + 4 * kPadding;
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int height = kFontHeight + kGraphHeight + 4 * kPadding + 2;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left = bounds().width() - width - right;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect area = SkRect::MakeXYWH(left, top, width, height);
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds =
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkRect::MakeXYWH(left + kPadding,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       top + kPadding,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kGraphWidth + kHistogramWidth + kGap + 2,
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kFontHeight);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds.bottom() + 2 * kPadding,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphHeight);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect histogram_bounds = SkRect::MakeXYWH(graph_bounds.right() + kGap,
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             graph_bounds.top(),
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             kHistogramWidth,
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             kGraphHeight);
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string value_text =
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("FPS:%5.1f", fps_graph_.value);
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string min_max_text =
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%.0f-%.0f", fps_graph_.min, fps_graph_.max);
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           value_text,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.left(),
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           min_max_text,
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kRight_Align,
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.right(),
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphLines(canvas, &paint, graph_bounds, fps_graph_);
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Collect graph and histogram data.
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPath path;
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kHistogramSize = 20;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double histogram[kHistogramSize] = { 1.0 };
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double max_bucket_value = 1.0;
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (FrameRateCounter::RingBufferType::Iterator it = --fps_counter->end(); it;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       --it) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta delta = fps_counter->RecentFrameInterval(it.index() + 1);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Skip this particular instantaneous frame rate if it is not likely to have
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // been valid.
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!fps_counter->IsBadFrameInterval(delta)) {
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double fps = 1.0 / delta.InSecondsF();
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Clamp the FPS to the range we want to plot visually.
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double p = fps / fps_graph_.current_upper_bound;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (p > 1.0)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p = 1.0;
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Plot this data point.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkPoint cur =
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SkPoint::Make(graph_bounds.left() + it.index(),
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        graph_bounds.bottom() - p * graph_bounds.height());
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (path.isEmpty())
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        path.moveTo(cur);
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        path.lineTo(cur);
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Use the fps value to find the right bucket in the histogram.
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int bucket_index = floor(p * (kHistogramSize - 1));
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Add the delta time to take the time spent at that fps rate into
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // account.
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      histogram[bucket_index] += delta.InSecondsF();
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_bucket_value = std::max(histogram[bucket_index], max_bucket_value);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw FPS histogram.
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::HUDSeparatorLineColor());
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(histogram_bounds.left() - 1,
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.top() - 1,
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.left() - 1,
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.bottom() + 1,
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   paint);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(histogram_bounds.right() + 1,
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.top() - 1,
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.right() + 1,
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.bottom() + 1,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   paint);
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double bar_height = histogram_bounds.height() / kHistogramSize;
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = kHistogramSize - 1; i >= 0; --i) {
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (histogram[i] > 0) {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double bar_width =
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          histogram[i] / max_bucket_value * histogram_bounds.width();
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      canvas->drawRect(
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SkRect::MakeXYWH(histogram_bounds.left(),
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           histogram_bounds.bottom() - (i + 1) * bar_height,
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bar_width,
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           1),
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          paint);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw FPS graph.
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setAntiAlias(true);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setStyle(SkPaint::kStroke_Style);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setStrokeWidth(1);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawPath(path, paint);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(SkCanvas* canvas,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int right,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int top,
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int width) const {
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!memory_entry_.bytes_total())
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkRect::MakeEmpty();
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 13;
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int height = 3 * kFontHeight + 4 * kPadding;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int left = bounds().width() - width - right;
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkRect area = SkRect::MakeXYWH(left, top, width, height);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double megabyte = 1024.0 * 1024.0;
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint title_pos = SkPoint::Make(left + kPadding, top + kFontHeight);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint stat1_pos = SkPoint::Make(left + width - kPadding - 1,
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    top + kPadding + 2 * kFontHeight);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1,
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    top + 2 * kPadding + 3 * kFontHeight);
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::MemoryDisplayTextColor());
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "GPU memory",
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           title_pos);
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string text =
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%6.1f MB used",
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         (memory_entry_.bytes_unreleasable +
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          memory_entry_.bytes_allocated) / megabyte);
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat1_pos);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (memory_entry_.bytes_over) {
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(SK_ColorRED);
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    text = base::StringPrintf("%6.1f MB over",
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              memory_entry_.bytes_over / megabyte);
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    text = base::StringPrintf("%6.1f MB max ",
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              memory_entry_.total_budget_in_bytes / megabyte);
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat2_pos);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay(
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PaintTimeCounter* paint_time_counter,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top) const {
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 15;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphWidth = paint_time_counter->HistorySize();
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphHeight = 40;
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int width = kGraphWidth + 2 * kPadding;
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int height =
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kFontHeight + kGraphHeight + 4 * kPadding + 2 + kFontHeight + kPadding;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int left = bounds().width() - width - right;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkRect area = SkRect::MakeXYWH(left, top, width, height);
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds = SkRect::MakeXYWH(
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      left + kPadding, top + kPadding, kGraphWidth, kFontHeight);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds2 = SkRect::MakeXYWH(left + kPadding,
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds.bottom() + kPadding,
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kFontHeight);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds2.bottom() + 2 * kPadding,
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphHeight);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string value_text =
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%.1f", paint_time_graph_.value);
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string min_max_text = base::StringPrintf(
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "%.1f-%.1f", paint_time_graph_.min, paint_time_graph_.max);
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "Page paint time (ms)",
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.left(),
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           value_text,
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.left(),
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.bottom());
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           min_max_text,
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kRight_Align,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.right(),
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.bottom());
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (PaintTimeCounter::RingBufferType::Iterator it =
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           paint_time_counter->End();
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it;
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       --it) {
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    double pt = it->InMillisecondsF();
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pt == 0.0)
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double p = pt / paint_time_graph_.current_upper_bound;
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (p > 1.0)
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      p = 1.0;
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkRect::MakeXYWH(graph_bounds.left() + it.index(),
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         graph_bounds.bottom() - p * graph_bounds.height(),
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         1,
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         p * graph_bounds.height()),
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        paint);
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphLines(canvas, &paint, graph_bounds, paint_time_graph_);
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawDebugRects(
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DebugRectHistory* debug_rect_history) const {
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects();
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < debug_rects.size(); ++i) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkColor stroke_color = 0;
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkColor fill_color = 0;
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float stroke_width = 0.f;
592eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::string label_text;
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (debug_rects[i].type) {
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case PAINT_RECT_TYPE:
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::PaintRectBorderColor();
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::PaintRectFillColor();
5987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::PaintRectBorderWidth();
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case PROPERTY_CHANGED_RECT_TYPE:
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::PropertyChangedRectBorderColor();
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::PropertyChangedRectFillColor();
6037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::PropertyChangedRectBorderWidth();
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case SURFACE_DAMAGE_RECT_TYPE:
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::SurfaceDamageRectBorderColor();
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::SurfaceDamageRectFillColor();
6087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::SurfaceDamageRectBorderWidth();
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case REPLICA_SCREEN_SPACE_RECT_TYPE:
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor();
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::ScreenSpaceSurfaceReplicaRectFillColor();
6137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth();
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case SCREEN_SPACE_RECT_TYPE:
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::ScreenSpaceLayerRectBorderColor();
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::ScreenSpaceLayerRectFillColor();
6187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::ScreenSpaceLayerRectBorderWidth();
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case OCCLUDING_RECT_TYPE:
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::OccludingRectBorderColor();
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::OccludingRectFillColor();
6237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::OccludingRectBorderWidth();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NONOCCLUDING_RECT_TYPE:
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::NonOccludingRectBorderColor();
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::NonOccludingRectFillColor();
6287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::NonOccludingRectBorderWidth();
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
630eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case TOUCH_EVENT_HANDLER_RECT_TYPE:
631eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stroke_color = DebugColors::TouchEventHandlerRectBorderColor();
632eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        fill_color = DebugColors::TouchEventHandlerRectFillColor();
6337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::TouchEventHandlerRectBorderWidth();
634eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        label_text = "touch event listener";
635eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
636eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case WHEEL_EVENT_HANDLER_RECT_TYPE:
637eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stroke_color = DebugColors::WheelEventHandlerRectBorderColor();
638eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        fill_color = DebugColors::WheelEventHandlerRectFillColor();
6397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::WheelEventHandlerRectBorderWidth();
640eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        label_text = "mousewheel event listener";
641eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
642eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      case NON_FAST_SCROLLABLE_RECT_TYPE:
643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        stroke_color = DebugColors::NonFastScrollableRectBorderColor();
644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        fill_color = DebugColors::NonFastScrollableRectFillColor();
6457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        stroke_width = DebugColors::NonFastScrollableRectBorderWidth();
646eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        label_text = "repaints on scroll";
647eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        break;
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    gfx::RectF debug_layer_rect = gfx::ScaleRect(debug_rects[i].rect,
6517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                 1.0 / contents_scale_x(),
6527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                                 1.0 / contents_scale_y());
6537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SkRect sk_rect = RectFToSkRect(debug_layer_rect);
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(fill_color);
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStyle(SkPaint::kFill_Style);
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(sk_rect, paint);
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(stroke_color);
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStyle(SkPaint::kStroke_Style);
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStrokeWidth(SkFloatToScalar(stroke_width));
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(sk_rect, paint);
662eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
663eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (label_text.length()) {
664eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const int kFontHeight = 12;
665eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const int kPadding = 3;
666eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
667eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->save();
668eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->clipRect(sk_rect);
669eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->translate(sk_rect.x(), sk_rect.y());
670eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
671eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      SkPaint label_paint = CreatePaint();
672eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_paint.setTextSize(kFontHeight);
673eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_paint.setTypeface(typeface_.get());
674eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_paint.setColor(stroke_color);
675eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
676eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const SkScalar label_text_width =
677eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          label_paint.measureText(label_text.c_str(), label_text.length());
678eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding,
679eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                      kFontHeight + 2 * kPadding),
680eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       label_paint);
681eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
682eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_paint.setAntiAlias(true);
683eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      label_paint.setColor(SkColorSetARGB(255, 50, 50, 50));
684eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->drawText(label_text.c_str(),
685eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       label_text.length(),
686eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       kPadding,
687eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       kFontHeight * 0.8f + kPadding,
688eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       label_paint);
689eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
690eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      canvas->restore();
691eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* HeadsUpDisplayLayerImpl::LayerTypeAsString() const {
696a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return "cc::HeadsUpDisplayLayerImpl";
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
700