heads_up_display_layer_impl.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stringprintf.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/debug_colors.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/debug_rect_history.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/frame_rate_counter.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/debug/paint_time_counter.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/layers/quad_sink.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/renderer.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/quads/texture_draw_quad.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/memory_history.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/tile_manager.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/trees/layer_tree_impl.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/platform_canvas.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2ext.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkPaint.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkTypeface.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static inline SkPaint CreatePaint() {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if (SK_R32_SHIFT || SK_B32_SHIFT != 16)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // swizzle our colors when drawing to the SkCanvas.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkColorMatrix swizzle_matrix;
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = 0; i < 20; ++i)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    swizzle_matrix.fMat[i] = 0;
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[0 + 5 * 2] = 1;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[1 + 5 * 1] = 1;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[2 + 5 * 0] = 1;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  swizzle_matrix.fMat[3 + 5 * 3] = 1;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  skia::RefPtr<SkColorMatrixFilter> filter =
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      skia::AdoptRef(new SkColorMatrixFilter(swizzle_matrix));
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColorFilter(filter.get());
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return paint;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      double start_upper_bound)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : value(0.0),
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      min(0.0),
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max(0.0),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_upper_bound(start_upper_bound),
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      default_upper_bound(start_upper_bound),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      indicator(indicator_value) {}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)double HeadsUpDisplayLayerImpl::Graph::UpdateUpperBound() {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double target_upper_bound = std::max(max, default_upper_bound);
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  current_upper_bound += (target_upper_bound - current_upper_bound) * 0.5;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return current_upper_bound;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 int id)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : LayerImpl(tree_impl, id),
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      typeface_(skia::AdoptRef(
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SkTypeface::CreateFromName("monospace", SkTypeface::kBold))),
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fps_graph_(60.0, 80.0),
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      paint_time_graph_(16.0, 48.0) {}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<LayerImpl> HeadsUpDisplayLayerImpl::CreateLayerImpl(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LayerTreeImpl* tree_impl) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return HeadsUpDisplayLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::WillDraw(ResourceProvider* resource_provider) {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl::WillDraw(resource_provider);
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): Scale the HUD by device scale to make it more friendly under
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // high DPI.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(danakj): The HUD could swap between two textures instead of creating a
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // texture every frame in ubercompositor.
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (hud_resource_->size() != bounds() ||
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      resource_provider->InUseByConsumer(hud_resource_->id()))
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hud_resource_->Free();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id()) {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    hud_resource_->Allocate(
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bounds(), GL_RGBA, ResourceProvider::TextureUsageAny);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::AppendQuads(QuadSink* quad_sink,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                          AppendQuadsData* append_quads_data) {
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id())
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SharedQuadState* shared_quad_state =
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      quad_sink->UseSharedQuadState(CreateSharedQuadState());
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect quad_rect(bounds());
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool premultiplied_alpha = true;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF uv_top_left(0.f, 0.f);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::PointF uv_bottom_right(1.f, 1.f);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const float vertex_opacity[] = { 1.f, 1.f, 1.f, 1.f };
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool flipped = false;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quad->SetNew(shared_quad_state,
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               quad_rect,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               opaque_rect,
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               hud_resource_->id(),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               premultiplied_alpha,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               uv_top_left,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               uv_bottom_right,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               vertex_opacity,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               flipped);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::UpdateHudTexture(
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResourceProvider* resource_provider) {
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id())
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkISize canvas_size;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (hud_canvas_)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas_size = hud_canvas_->getDeviceSize();
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas_size.set(0, 0);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (canvas_size.fWidth != bounds().width() ||
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      canvas_size.fHeight != bounds().height() || !hud_canvas_) {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool opaque = false;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hud_canvas_ = make_scoped_ptr(
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        skia::CreateBitmapCanvas(bounds().width(), bounds().height(), opaque));
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateHudContents();
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0));
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawHudContents(hud_canvas_.get());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkBitmap* bitmap = &hud_canvas_->getDevice()->accessBitmap(false);
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkAutoLockPixels locker(*bitmap);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect layer_rect(bounds());
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  resource_provider->SetPixels(hud_resource_->id(),
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               static_cast<const uint8_t*>(bitmap->getPixels()),
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               layer_rect,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               layer_rect,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               gfx::Vector2d());
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DidDraw(ResourceProvider* resource_provider) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LayerImpl::DidDraw(resource_provider);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!hud_resource_->id())
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // FIXME: the following assert will not be true when sending resources to a
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // parent compositor. We will probably need to hold on to hud_resource_ for
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // longer, and have several HUD textures in the pipeline.
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!resource_provider->InUseByConsumer(hud_resource_->id()));
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DidLoseOutputSurface() { hud_resource_.reset(); }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HeadsUpDisplayLayerImpl::LayerIsAlwaysDamaged() const { return true; }
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::UpdateHudContents() {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Don't update numbers every frame so text is readable.
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeTicks now = layer_tree_impl()->CurrentFrameTimeTicks();
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (base::TimeDelta(now - time_of_last_graph_update_).InSecondsF() > 0.25f) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    time_of_last_graph_update_ = now;
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.show_fps_counter) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter();
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fps_graph_.value = fps_counter->GetAverageFPS();
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.continuous_painting) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PaintTimeCounter* paint_time_counter =
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          layer_tree_impl()->paint_time_counter();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta latest, min, max;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (paint_time_counter->End())
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        latest = **paint_time_counter->End();
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_counter->GetMinAndMaxPaintTime(&min, &max);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.value = latest.InMillisecondsF();
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.min = min.InMillisecondsF();
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      paint_time_graph_.max = max.InMillisecondsF();
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (debug_state.ShowMemoryStats()) {
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MemoryHistory* memory_history = layer_tree_impl()->memory_history();
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (memory_history->End())
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memory_entry_ = **memory_history->End();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        memory_entry_ = MemoryHistory::Entry();
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  fps_graph_.UpdateUpperBound();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint_time_graph_.UpdateUpperBound();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) const {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.ShowHudRects())
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history());
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.show_platform_layer_tree)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawPlatformLayerTree(canvas);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect area = SkRect::MakeEmpty();
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.continuous_painting) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Don't show the FPS display when continuous painting is enabled, because
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // it would show misleading numbers.
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    area = DrawPaintTimeDisplay(
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        canvas, layer_tree_impl()->paint_time_counter(), 0, 0);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (debug_state.show_fps_counter) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    area =
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (debug_state.ShowMemoryStats())
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawMemoryDisplay(canvas, 0, area.bottom(), SkMaxScalar(area.width(), 150));
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint* paint,
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& text,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint::Align align,
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int size,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int x,
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int y) const {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const bool anti_alias = paint->isAntiAlias();
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setAntiAlias(true);
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTextSize(size);
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTextAlign(align);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setTypeface(typeface_.get());
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawText(text.c_str(), text.length(), x, y, *paint);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setAntiAlias(anti_alias);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint* paint,
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const std::string& text,
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       SkPaint::Align align,
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       int size,
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       const SkPoint& pos) const {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, paint, text, align, size, pos.x(), pos.y());
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawGraphBackground(SkCanvas* canvas,
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  SkPaint* paint,
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  const SkRect& bounds) const {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDBackgroundColor());
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawRect(bounds, *paint);
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawGraphLines(SkCanvas* canvas,
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             SkPaint* paint,
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const SkRect& bounds,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             const Graph& graph) const {
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw top and bottom line.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDSeparatorLineColor());
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(bounds.left(),
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() - 1,
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.right(),
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() - 1,
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   *paint);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.left(), bounds.bottom(), bounds.right(), bounds.bottom(), *paint);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw indicator line (additive blend mode to increase contrast when drawn on
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // top of graph).
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setColor(DebugColors::HUDIndicatorLineColor());
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setXfermodeMode(SkXfermode::kPlus_Mode);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double indicator_top =
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) -
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1.0;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(bounds.left(),
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() + indicator_top,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.right(),
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   bounds.top() + indicator_top,
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   *paint);
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint->setXfermode(NULL);
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawPlatformLayerTree(SkCanvas* canvas) const {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 14;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      canvas,
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &paint,
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()));
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string layer_tree = layer_tree_impl()->layer_tree_as_text();
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> lines;
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SplitString(layer_tree, '\n', &lines);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::PlatformLayerTreeTextColor());
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0;
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i < lines.size() &&
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           static_cast<int>(2 + i * kFontHeight) < bounds().height();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DrawText(canvas,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             &paint,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             lines[i],
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             SkPaint::kLeft_Align,
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             kFontHeight,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             2,
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             2 + (i + 1) * kFontHeight);
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const FrameRateCounter* fps_counter,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top) const {
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGap = 6;
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 15;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphWidth = fps_counter->time_stamp_history_size() - 2;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphHeight = 40;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kHistogramWidth = 37;
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int width = kGraphWidth + kHistogramWidth + 4 * kPadding;
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int height = kFontHeight + kGraphHeight + 4 * kPadding + 2;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int left = bounds().width() - width - right;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect area = SkRect::MakeXYWH(left, top, width, height);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds =
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkRect::MakeXYWH(left + kPadding,
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       top + kPadding,
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kGraphWidth + kHistogramWidth + kGap + 2,
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       kFontHeight);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds.bottom() + 2 * kPadding,
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphHeight);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect histogram_bounds = SkRect::MakeXYWH(graph_bounds.right() + kGap,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             graph_bounds.top(),
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             kHistogramWidth,
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             kGraphHeight);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string value_text =
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("FPS:%5.1f", fps_graph_.value);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string min_max_text =
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%.0f-%.0f", fps_graph_.min, fps_graph_.max);
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           value_text,
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.left(),
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           min_max_text,
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kRight_Align,
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.right(),
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphLines(canvas, &paint, graph_bounds, fps_graph_);
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Collect graph and histogram data.
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPath path;
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kHistogramSize = 20;
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double histogram[kHistogramSize] = { 1.0 };
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  double max_bucket_value = 1.0;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (FrameRateCounter::RingBufferType::Iterator it = --fps_counter->end(); it;
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       --it) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta delta = fps_counter->RecentFrameInterval(it.index() + 1);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Skip this particular instantaneous frame rate if it is not likely to have
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // been valid.
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!fps_counter->IsBadFrameInterval(delta)) {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double fps = 1.0 / delta.InSecondsF();
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Clamp the FPS to the range we want to plot visually.
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double p = fps / fps_graph_.current_upper_bound;
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (p > 1.0)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        p = 1.0;
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Plot this data point.
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SkPoint cur =
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SkPoint::Make(graph_bounds.left() + it.index(),
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        graph_bounds.bottom() - p * graph_bounds.height());
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (path.isEmpty())
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        path.moveTo(cur);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      else
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        path.lineTo(cur);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Use the fps value to find the right bucket in the histogram.
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int bucket_index = floor(p * (kHistogramSize - 1));
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Add the delta time to take the time spent at that fps rate into
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // account.
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      histogram[bucket_index] += delta.InSecondsF();
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_bucket_value = std::max(histogram[bucket_index], max_bucket_value);
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw FPS histogram.
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::HUDSeparatorLineColor());
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(histogram_bounds.left() - 1,
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.top() - 1,
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.left() - 1,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.bottom() + 1,
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   paint);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawLine(histogram_bounds.right() + 1,
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.top() - 1,
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.right() + 1,
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   histogram_bounds.bottom() + 1,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   paint);
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double bar_height = histogram_bounds.height() / kHistogramSize;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = kHistogramSize - 1; i >= 0; --i) {
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (histogram[i] > 0) {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      double bar_width =
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          histogram[i] / max_bucket_value * histogram_bounds.width();
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      canvas->drawRect(
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          SkRect::MakeXYWH(histogram_bounds.left(),
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           histogram_bounds.bottom() - (i + 1) * bar_height,
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           bar_width,
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           1),
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          paint);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Draw FPS graph.
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setAntiAlias(true);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setStyle(SkPaint::kStroke_Style);
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setStrokeWidth(1);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->drawPath(path, paint);
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(SkCanvas* canvas,
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int right,
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int top,
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                  int width) const {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!memory_entry_.bytes_total())
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return SkRect::MakeEmpty();
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 13;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int height = 3 * kFontHeight + 4 * kPadding;
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int left = bounds().width() - width - right;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkRect area = SkRect::MakeXYWH(left, top, width, height);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const double megabyte = 1024.0 * 1024.0;
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint title_pos = SkPoint::Make(left + kPadding, top + kFontHeight);
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint stat1_pos = SkPoint::Make(left + width - kPadding - 1,
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    top + kPadding + 2 * kFontHeight);
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1,
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    top + 2 * kPadding + 3 * kFontHeight);
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::MemoryDisplayTextColor());
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "GPU memory",
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           title_pos);
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string text =
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%6.1f MB used",
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         (memory_entry_.bytes_unreleasable +
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          memory_entry_.bytes_allocated) / megabyte);
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat1_pos);
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (memory_entry_.bytes_over) {
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(SK_ColorRED);
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    text = base::StringPrintf("%6.1f MB over",
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              memory_entry_.bytes_over / megabyte);
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    text = base::StringPrintf("%6.1f MB max ",
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              memory_entry_.total_budget_in_bytes / megabyte);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat2_pos);
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay(
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PaintTimeCounter* paint_time_counter,
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int right,
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top) const {
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kPadding = 4;
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kFontHeight = 15;
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphWidth = paint_time_counter->HistorySize();
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kGraphHeight = 40;
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int width = kGraphWidth + 2 * kPadding;
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int height =
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kFontHeight + kGraphHeight + 4 * kPadding + 2 + kFontHeight + kPadding;
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int left = bounds().width() - width - right;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const SkRect area = SkRect::MakeXYWH(left, top, width, height);
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphBackground(canvas, &paint, area);
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds = SkRect::MakeXYWH(
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      left + kPadding, top + kPadding, kGraphWidth, kFontHeight);
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect text_bounds2 = SkRect::MakeXYWH(left + kPadding,
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds.bottom() + kPadding,
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kFontHeight);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         text_bounds2.bottom() + 2 * kPadding,
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphWidth,
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         kGraphHeight);
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string value_text =
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("%.1f", paint_time_graph_.value);
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string min_max_text = base::StringPrintf(
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      "%.1f-%.1f", paint_time_graph_.min, paint_time_graph_.max);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           "Page paint time (ms)",
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.left(),
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds.bottom());
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           value_text,
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kLeft_Align,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.left(),
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.bottom());
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawText(canvas,
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           &paint,
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           min_max_text,
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SkPaint::kRight_Align,
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           kFontHeight,
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.right(),
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           text_bounds2.bottom());
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (PaintTimeCounter::RingBufferType::Iterator it =
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           paint_time_counter->End();
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it;
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       --it) {
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    double pt = it->InMillisecondsF();
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (pt == 0.0)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double p = pt / paint_time_graph_.current_upper_bound;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (p > 1.0)
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      p = 1.0;
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkRect::MakeXYWH(graph_bounds.left() + it.index(),
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         graph_bounds.bottom() - p * graph_bounds.height(),
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         1,
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         p * graph_bounds.height()),
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        paint);
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DrawGraphLines(canvas, &paint, graph_bounds, paint_time_graph_);
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return area;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HeadsUpDisplayLayerImpl::DrawDebugRects(
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkCanvas* canvas,
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DebugRectHistory* debug_rect_history) const {
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects();
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float rect_scale = 1.f / layer_tree_impl()->device_scale_factor();
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SkPaint paint = CreatePaint();
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->save();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->scale(rect_scale, rect_scale);
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < debug_rects.size(); ++i) {
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkColor stroke_color = 0;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkColor fill_color = 0;
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float stroke_width = 0.f;
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (debug_rects[i].type) {
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case PAINT_RECT_TYPE:
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::PaintRectBorderColor();
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::PaintRectFillColor();
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width = DebugColors::PaintRectBorderWidth(layer_tree_impl());
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case PROPERTY_CHANGED_RECT_TYPE:
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::PropertyChangedRectBorderColor();
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::PropertyChangedRectFillColor();
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width =
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DebugColors::PropertyChangedRectBorderWidth(layer_tree_impl());
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case SURFACE_DAMAGE_RECT_TYPE:
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::SurfaceDamageRectBorderColor();
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::SurfaceDamageRectFillColor();
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width =
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DebugColors::SurfaceDamageRectBorderWidth(layer_tree_impl());
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case REPLICA_SCREEN_SPACE_RECT_TYPE:
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor();
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::ScreenSpaceSurfaceReplicaRectFillColor();
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width = DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth(
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            layer_tree_impl());
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case SCREEN_SPACE_RECT_TYPE:
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::ScreenSpaceLayerRectBorderColor();
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::ScreenSpaceLayerRectFillColor();
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width =
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DebugColors::ScreenSpaceLayerRectBorderWidth(layer_tree_impl());
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case OCCLUDING_RECT_TYPE:
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::OccludingRectBorderColor();
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::OccludingRectFillColor();
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width = DebugColors::OccludingRectBorderWidth(layer_tree_impl());
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case NONOCCLUDING_RECT_TYPE:
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_color = DebugColors::NonOccludingRectBorderColor();
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fill_color = DebugColors::NonOccludingRectFillColor();
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        stroke_width =
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            DebugColors::NonOccludingRectBorderWidth(layer_tree_impl());
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::RectF& rect = debug_rects[i].rect;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkRect sk_rect =
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(fill_color);
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStyle(SkPaint::kFill_Style);
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(sk_rect, paint);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setColor(stroke_color);
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStyle(SkPaint::kStroke_Style);
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    paint.setStrokeWidth(SkFloatToScalar(stroke_width));
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    canvas->drawRect(sk_rect, paint);
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  canvas->restore();
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* HeadsUpDisplayLayerImpl::LayerTypeAsString() const {
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return "HeadsUpDisplayLayer";
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
695