ServiceWorker: Introduce SWMessageSender in order to mock IPC messaging
[chromium-blink-merge.git] / cc / layers / heads_up_display_layer_impl.cc
blobe1a9daf1ea5e8ba7b8c5436e923ed37655da5a6d
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layers/heads_up_display_layer_impl.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/strings/stringprintf.h"
11 #include "base/trace_event/trace_event.h"
12 #include "base/trace_event/trace_event_argument.h"
13 #include "cc/debug/debug_colors.h"
14 #include "cc/debug/frame_rate_counter.h"
15 #include "cc/debug/paint_time_counter.h"
16 #include "cc/output/begin_frame_args.h"
17 #include "cc/output/renderer.h"
18 #include "cc/quads/texture_draw_quad.h"
19 #include "cc/resources/memory_history.h"
20 #include "cc/trees/layer_tree_host_impl.h"
21 #include "cc/trees/layer_tree_impl.h"
22 #include "skia/ext/platform_canvas.h"
23 #include "third_party/skia/include/core/SkPaint.h"
24 #include "third_party/skia/include/core/SkTypeface.h"
25 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
26 #include "ui/gfx/geometry/point.h"
27 #include "ui/gfx/geometry/size.h"
28 #include "ui/gfx/geometry/size_conversions.h"
29 #include "ui/gfx/hud_font.h"
31 namespace cc {
33 static inline SkPaint CreatePaint() {
34 SkPaint paint;
35 #if (SK_R32_SHIFT || SK_B32_SHIFT != 16)
36 // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to
37 // swizzle our colors when drawing to the SkCanvas.
38 SkColorMatrix swizzle_matrix;
39 for (int i = 0; i < 20; ++i)
40 swizzle_matrix.fMat[i] = 0;
41 swizzle_matrix.fMat[0 + 5 * 2] = 1;
42 swizzle_matrix.fMat[1 + 5 * 1] = 1;
43 swizzle_matrix.fMat[2 + 5 * 0] = 1;
44 swizzle_matrix.fMat[3 + 5 * 3] = 1;
46 skia::RefPtr<SkColorMatrixFilter> filter =
47 skia::AdoptRef(SkColorMatrixFilter::Create(swizzle_matrix));
48 paint.setColorFilter(filter.get());
49 #endif
50 return paint;
53 HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value,
54 double start_upper_bound)
55 : value(0.0),
56 min(0.0),
57 max(0.0),
58 current_upper_bound(start_upper_bound),
59 default_upper_bound(start_upper_bound),
60 indicator(indicator_value) {}
62 double HeadsUpDisplayLayerImpl::Graph::UpdateUpperBound() {
63 double target_upper_bound = std::max(max, default_upper_bound);
64 current_upper_bound += (target_upper_bound - current_upper_bound) * 0.5;
65 return current_upper_bound;
68 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl,
69 int id)
70 : LayerImpl(tree_impl, id),
71 typeface_(gfx::GetHudTypeface()),
72 internal_contents_scale_(1.f),
73 fps_graph_(60.0, 80.0),
74 paint_time_graph_(16.0, 48.0),
75 fade_step_(0) {
76 if (!typeface_) {
77 typeface_ = skia::AdoptRef(
78 SkTypeface::CreateFromName("monospace", SkTypeface::kBold));
82 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {}
84 scoped_ptr<LayerImpl> HeadsUpDisplayLayerImpl::CreateLayerImpl(
85 LayerTreeImpl* tree_impl) {
86 return HeadsUpDisplayLayerImpl::Create(tree_impl, id());
89 void HeadsUpDisplayLayerImpl::AcquireResource(
90 ResourceProvider* resource_provider) {
91 for (ScopedPtrVector<ScopedResource>::iterator it = resources_.begin();
92 it != resources_.end();
93 ++it) {
94 if (!resource_provider->InUseByConsumer((*it)->id())) {
95 resources_.swap(it, resources_.end() - 1);
96 return;
100 scoped_ptr<ScopedResource> resource =
101 ScopedResource::Create(resource_provider);
102 resource->Allocate(internal_content_bounds_,
103 ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888);
104 resources_.push_back(resource.Pass());
107 class ResourceSizeIsEqualTo {
108 public:
109 explicit ResourceSizeIsEqualTo(const gfx::Size& size_)
110 : compare_size_(size_) {}
112 bool operator()(const ScopedResource* resource) {
113 return resource->size() == compare_size_;
116 private:
117 const gfx::Size compare_size_;
120 void HeadsUpDisplayLayerImpl::ReleaseUnmatchedSizeResources(
121 ResourceProvider* resource_provider) {
122 ScopedPtrVector<ScopedResource>::iterator it_erase =
123 resources_.partition(ResourceSizeIsEqualTo(internal_content_bounds_));
124 resources_.erase(it_erase, resources_.end());
127 bool HeadsUpDisplayLayerImpl::WillDraw(DrawMode draw_mode,
128 ResourceProvider* resource_provider) {
129 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
130 return false;
132 internal_contents_scale_ = draw_properties().ideal_contents_scale;
133 internal_content_bounds_ =
134 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_));
136 ReleaseUnmatchedSizeResources(resource_provider);
137 AcquireResource(resource_provider);
138 return LayerImpl::WillDraw(draw_mode, resource_provider);
141 void HeadsUpDisplayLayerImpl::AppendQuads(
142 RenderPass* render_pass,
143 AppendQuadsData* append_quads_data) {
144 if (!resources_.back()->id())
145 return;
147 SharedQuadState* shared_quad_state =
148 render_pass->CreateAndAppendSharedQuadState();
149 PopulateScaledSharedQuadState(shared_quad_state, internal_contents_scale_);
151 gfx::Rect quad_rect(internal_content_bounds_);
152 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect());
153 gfx::Rect visible_quad_rect(quad_rect);
154 bool premultiplied_alpha = true;
155 gfx::PointF uv_top_left(0.f, 0.f);
156 gfx::PointF uv_bottom_right(1.f, 1.f);
157 const float vertex_opacity[] = { 1.f, 1.f, 1.f, 1.f };
158 bool flipped = false;
159 bool nearest_neighbor = false;
160 TextureDrawQuad* quad =
161 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
162 quad->SetNew(shared_quad_state,
163 quad_rect,
164 opaque_rect,
165 visible_quad_rect,
166 resources_.back()->id(),
167 premultiplied_alpha,
168 uv_top_left,
169 uv_bottom_right,
170 SK_ColorTRANSPARENT,
171 vertex_opacity,
172 flipped,
173 nearest_neighbor);
176 void HeadsUpDisplayLayerImpl::UpdateHudTexture(
177 DrawMode draw_mode,
178 ResourceProvider* resource_provider) {
179 if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE || !resources_.back()->id())
180 return;
182 SkISize canvas_size;
183 if (hud_surface_)
184 canvas_size = hud_surface_->getCanvas()->getDeviceSize();
185 else
186 canvas_size.set(0, 0);
188 if (canvas_size.width() != internal_content_bounds_.width() ||
189 canvas_size.height() != internal_content_bounds_.height() ||
190 !hud_surface_) {
191 TRACE_EVENT0("cc", "ResizeHudCanvas");
193 hud_surface_ = skia::AdoptRef(SkSurface::NewRasterN32Premul(
194 internal_content_bounds_.width(), internal_content_bounds_.height()));
197 UpdateHudContents();
200 TRACE_EVENT0("cc", "DrawHudContents");
201 hud_surface_->getCanvas()->clear(SkColorSetARGB(0, 0, 0, 0));
202 hud_surface_->getCanvas()->save();
203 hud_surface_->getCanvas()->scale(internal_contents_scale_,
204 internal_contents_scale_);
206 DrawHudContents(hud_surface_->getCanvas());
208 hud_surface_->getCanvas()->restore();
211 TRACE_EVENT0("cc", "UploadHudTexture");
212 SkImageInfo info;
213 size_t row_bytes = 0;
214 const void* pixels = hud_surface_->getCanvas()->peekPixels(&info, &row_bytes);
215 DCHECK(pixels);
216 DCHECK(info.colorType() == kN32_SkColorType);
217 resource_provider->CopyToResource(resources_.back()->id(),
218 static_cast<const uint8_t*>(pixels),
219 internal_content_bounds_);
222 void HeadsUpDisplayLayerImpl::ReleaseResources() {
223 resources_.clear();
226 void HeadsUpDisplayLayerImpl::UpdateHudContents() {
227 const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
229 // Don't update numbers every frame so text is readable.
230 base::TimeTicks now = layer_tree_impl()->CurrentBeginFrameArgs().frame_time;
231 if (base::TimeDelta(now - time_of_last_graph_update_).InSecondsF() > 0.25f) {
232 time_of_last_graph_update_ = now;
234 if (debug_state.show_fps_counter) {
235 FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter();
236 fps_graph_.value = fps_counter->GetAverageFPS();
237 fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max);
240 if (debug_state.continuous_painting) {
241 PaintTimeCounter* paint_time_counter =
242 layer_tree_impl()->paint_time_counter();
243 base::TimeDelta latest, min, max;
245 if (paint_time_counter->End())
246 latest = **paint_time_counter->End();
247 paint_time_counter->GetMinAndMaxPaintTime(&min, &max);
249 paint_time_graph_.value = latest.InMillisecondsF();
250 paint_time_graph_.min = min.InMillisecondsF();
251 paint_time_graph_.max = max.InMillisecondsF();
254 if (debug_state.ShowMemoryStats()) {
255 MemoryHistory* memory_history = layer_tree_impl()->memory_history();
256 if (memory_history->End())
257 memory_entry_ = **memory_history->End();
258 else
259 memory_entry_ = MemoryHistory::Entry();
263 fps_graph_.UpdateUpperBound();
264 paint_time_graph_.UpdateUpperBound();
267 void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) {
268 const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state();
270 if (debug_state.ShowHudRects()) {
271 DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history());
272 if (IsAnimatingHUDContents()) {
273 layer_tree_impl()->SetNeedsRedraw();
277 SkRect area = SkRect::MakeEmpty();
278 if (debug_state.continuous_painting) {
279 area = DrawPaintTimeDisplay(
280 canvas, layer_tree_impl()->paint_time_counter(), 0, 0);
281 } else if (debug_state.show_fps_counter) {
282 // Don't show the FPS display when continuous painting is enabled, because
283 // it would show misleading numbers.
284 area =
285 DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0);
288 if (debug_state.show_fps_counter || debug_state.continuous_painting) {
289 area = DrawGpuRasterizationStatus(canvas, 0, area.bottom(),
290 SkMaxScalar(area.width(), 150));
293 if (debug_state.ShowMemoryStats())
294 DrawMemoryDisplay(canvas, 0, area.bottom(), SkMaxScalar(area.width(), 150));
297 void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
298 SkPaint* paint,
299 const std::string& text,
300 SkPaint::Align align,
301 int size,
302 int x,
303 int y) const {
304 const bool anti_alias = paint->isAntiAlias();
305 paint->setAntiAlias(true);
307 paint->setTextSize(size);
308 paint->setTextAlign(align);
309 paint->setTypeface(typeface_.get());
310 canvas->drawText(text.c_str(), text.length(), x, y, *paint);
312 paint->setAntiAlias(anti_alias);
315 void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas,
316 SkPaint* paint,
317 const std::string& text,
318 SkPaint::Align align,
319 int size,
320 const SkPoint& pos) const {
321 DrawText(canvas, paint, text, align, size, pos.x(), pos.y());
324 void HeadsUpDisplayLayerImpl::DrawGraphBackground(SkCanvas* canvas,
325 SkPaint* paint,
326 const SkRect& bounds) const {
327 paint->setColor(DebugColors::HUDBackgroundColor());
328 canvas->drawRect(bounds, *paint);
331 void HeadsUpDisplayLayerImpl::DrawGraphLines(SkCanvas* canvas,
332 SkPaint* paint,
333 const SkRect& bounds,
334 const Graph& graph) const {
335 // Draw top and bottom line.
336 paint->setColor(DebugColors::HUDSeparatorLineColor());
337 canvas->drawLine(bounds.left(),
338 bounds.top() - 1,
339 bounds.right(),
340 bounds.top() - 1,
341 *paint);
342 canvas->drawLine(
343 bounds.left(), bounds.bottom(), bounds.right(), bounds.bottom(), *paint);
345 // Draw indicator line (additive blend mode to increase contrast when drawn on
346 // top of graph).
347 paint->setColor(DebugColors::HUDIndicatorLineColor());
348 paint->setXfermodeMode(SkXfermode::kPlus_Mode);
349 const double indicator_top =
350 bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) -
351 1.0;
352 canvas->drawLine(bounds.left(),
353 bounds.top() + indicator_top,
354 bounds.right(),
355 bounds.top() + indicator_top,
356 *paint);
357 paint->setXfermode(nullptr);
360 SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay(
361 SkCanvas* canvas,
362 const FrameRateCounter* fps_counter,
363 int right,
364 int top) const {
365 const int kPadding = 4;
366 const int kGap = 6;
368 const int kFontHeight = 15;
370 const int kGraphWidth = fps_counter->time_stamp_history_size() - 2;
371 const int kGraphHeight = 40;
373 const int kHistogramWidth = 37;
375 int width = kGraphWidth + kHistogramWidth + 4 * kPadding;
376 int height = kFontHeight + kGraphHeight + 4 * kPadding + 2;
377 int left = bounds().width() - width - right;
378 SkRect area = SkRect::MakeXYWH(left, top, width, height);
380 SkPaint paint = CreatePaint();
381 DrawGraphBackground(canvas, &paint, area);
383 SkRect text_bounds =
384 SkRect::MakeXYWH(left + kPadding,
385 top + kPadding,
386 kGraphWidth + kHistogramWidth + kGap + 2,
387 kFontHeight);
388 SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
389 text_bounds.bottom() + 2 * kPadding,
390 kGraphWidth,
391 kGraphHeight);
392 SkRect histogram_bounds = SkRect::MakeXYWH(graph_bounds.right() + kGap,
393 graph_bounds.top(),
394 kHistogramWidth,
395 kGraphHeight);
397 const std::string value_text =
398 base::StringPrintf("FPS:%5.1f", fps_graph_.value);
399 const std::string min_max_text =
400 base::StringPrintf("%.0f-%.0f", fps_graph_.min, fps_graph_.max);
402 VLOG(1) << value_text;
404 paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
405 DrawText(canvas,
406 &paint,
407 value_text,
408 SkPaint::kLeft_Align,
409 kFontHeight,
410 text_bounds.left(),
411 text_bounds.bottom());
412 DrawText(canvas,
413 &paint,
414 min_max_text,
415 SkPaint::kRight_Align,
416 kFontHeight,
417 text_bounds.right(),
418 text_bounds.bottom());
420 DrawGraphLines(canvas, &paint, graph_bounds, fps_graph_);
422 // Collect graph and histogram data.
423 SkPath path;
425 const int kHistogramSize = 20;
426 double histogram[kHistogramSize] = { 1.0 };
427 double max_bucket_value = 1.0;
429 for (FrameRateCounter::RingBufferType::Iterator it = --fps_counter->end(); it;
430 --it) {
431 base::TimeDelta delta = fps_counter->RecentFrameInterval(it.index() + 1);
433 // Skip this particular instantaneous frame rate if it is not likely to have
434 // been valid.
435 if (!fps_counter->IsBadFrameInterval(delta)) {
436 double fps = 1.0 / delta.InSecondsF();
438 // Clamp the FPS to the range we want to plot visually.
439 double p = fps / fps_graph_.current_upper_bound;
440 if (p > 1.0)
441 p = 1.0;
443 // Plot this data point.
444 SkPoint cur =
445 SkPoint::Make(graph_bounds.left() + it.index(),
446 graph_bounds.bottom() - p * graph_bounds.height());
447 if (path.isEmpty())
448 path.moveTo(cur);
449 else
450 path.lineTo(cur);
452 // Use the fps value to find the right bucket in the histogram.
453 int bucket_index = floor(p * (kHistogramSize - 1));
455 // Add the delta time to take the time spent at that fps rate into
456 // account.
457 histogram[bucket_index] += delta.InSecondsF();
458 max_bucket_value = std::max(histogram[bucket_index], max_bucket_value);
462 // Draw FPS histogram.
463 paint.setColor(DebugColors::HUDSeparatorLineColor());
464 canvas->drawLine(histogram_bounds.left() - 1,
465 histogram_bounds.top() - 1,
466 histogram_bounds.left() - 1,
467 histogram_bounds.bottom() + 1,
468 paint);
469 canvas->drawLine(histogram_bounds.right() + 1,
470 histogram_bounds.top() - 1,
471 histogram_bounds.right() + 1,
472 histogram_bounds.bottom() + 1,
473 paint);
475 paint.setColor(DebugColors::FPSDisplayTextAndGraphColor());
476 const double bar_height = histogram_bounds.height() / kHistogramSize;
478 for (int i = kHistogramSize - 1; i >= 0; --i) {
479 if (histogram[i] > 0) {
480 double bar_width =
481 histogram[i] / max_bucket_value * histogram_bounds.width();
482 canvas->drawRect(
483 SkRect::MakeXYWH(histogram_bounds.left(),
484 histogram_bounds.bottom() - (i + 1) * bar_height,
485 bar_width,
487 paint);
491 // Draw FPS graph.
492 paint.setAntiAlias(true);
493 paint.setStyle(SkPaint::kStroke_Style);
494 paint.setStrokeWidth(1);
495 canvas->drawPath(path, paint);
497 return area;
500 SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(SkCanvas* canvas,
501 int right,
502 int top,
503 int width) const {
504 if (!memory_entry_.total_bytes_used)
505 return SkRect::MakeEmpty();
507 const int kPadding = 4;
508 const int kFontHeight = 13;
510 const int height = 3 * kFontHeight + 4 * kPadding;
511 const int left = bounds().width() - width - right;
512 const SkRect area = SkRect::MakeXYWH(left, top, width, height);
514 const double kMegabyte = 1024.0 * 1024.0;
516 SkPaint paint = CreatePaint();
517 DrawGraphBackground(canvas, &paint, area);
519 SkPoint title_pos = SkPoint::Make(left + kPadding, top + kFontHeight);
520 SkPoint stat1_pos = SkPoint::Make(left + width - kPadding - 1,
521 top + kPadding + 2 * kFontHeight);
522 SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1,
523 top + 2 * kPadding + 3 * kFontHeight);
525 paint.setColor(DebugColors::MemoryDisplayTextColor());
526 DrawText(canvas,
527 &paint,
528 "GPU memory",
529 SkPaint::kLeft_Align,
530 kFontHeight,
531 title_pos);
533 std::string text = base::StringPrintf(
534 "%6.1f MB used", memory_entry_.total_bytes_used / kMegabyte);
535 DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat1_pos);
537 if (!memory_entry_.had_enough_memory)
538 paint.setColor(SK_ColorRED);
539 text = base::StringPrintf("%6.1f MB max ",
540 memory_entry_.total_budget_in_bytes / kMegabyte);
541 DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat2_pos);
543 return area;
546 SkRect HeadsUpDisplayLayerImpl::DrawGpuRasterizationStatus(SkCanvas* canvas,
547 int right,
548 int top,
549 int width) const {
550 std::string status;
551 SkColor color = SK_ColorRED;
552 switch (layer_tree_impl()->GetGpuRasterizationStatus()) {
553 case GpuRasterizationStatus::ON:
554 status = "GPU raster: on";
555 color = SK_ColorGREEN;
556 break;
557 case GpuRasterizationStatus::ON_FORCED:
558 status = "GPU raster: on (forced)";
559 color = SK_ColorGREEN;
560 break;
561 case GpuRasterizationStatus::OFF_DEVICE:
562 status = "GPU raster: off (device)";
563 color = SK_ColorRED;
564 break;
565 case GpuRasterizationStatus::OFF_VIEWPORT:
566 status = "GPU raster: off (viewport)";
567 color = SK_ColorYELLOW;
568 break;
569 case GpuRasterizationStatus::OFF_CONTENT:
570 status = "GPU raster: off (content)";
571 color = SK_ColorYELLOW;
572 break;
575 if (status.empty())
576 return SkRect::MakeEmpty();
578 const int kPadding = 4;
579 const int kFontHeight = 13;
581 const int height = kFontHeight + 2 * kPadding;
582 const int left = bounds().width() - width - right;
583 const SkRect area = SkRect::MakeXYWH(left, top, width, height);
585 SkPaint paint = CreatePaint();
586 DrawGraphBackground(canvas, &paint, area);
588 SkPoint gpu_status_pos = SkPoint::Make(left + kPadding, top + kFontHeight);
590 paint.setColor(color);
591 DrawText(canvas, &paint, status, SkPaint::kLeft_Align, kFontHeight,
592 gpu_status_pos);
594 return area;
597 SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay(
598 SkCanvas* canvas,
599 const PaintTimeCounter* paint_time_counter,
600 int right,
601 int top) const {
602 const int kPadding = 4;
603 const int kFontHeight = 15;
605 const int kGraphWidth = paint_time_counter->HistorySize();
606 const int kGraphHeight = 40;
608 const int width = kGraphWidth + 2 * kPadding;
609 const int height =
610 kFontHeight + kGraphHeight + 4 * kPadding + 2 + kFontHeight + kPadding;
611 const int left = bounds().width() - width - right;
613 const SkRect area = SkRect::MakeXYWH(left, top, width, height);
615 SkPaint paint = CreatePaint();
616 DrawGraphBackground(canvas, &paint, area);
618 SkRect text_bounds = SkRect::MakeXYWH(
619 left + kPadding, top + kPadding, kGraphWidth, kFontHeight);
620 SkRect text_bounds2 = SkRect::MakeXYWH(left + kPadding,
621 text_bounds.bottom() + kPadding,
622 kGraphWidth,
623 kFontHeight);
624 SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding,
625 text_bounds2.bottom() + 2 * kPadding,
626 kGraphWidth,
627 kGraphHeight);
629 const std::string value_text =
630 base::StringPrintf("%.1f", paint_time_graph_.value);
631 const std::string min_max_text = base::StringPrintf(
632 "%.1f-%.1f", paint_time_graph_.min, paint_time_graph_.max);
634 paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
635 DrawText(canvas, &paint, "Compositor frame time (ms)", SkPaint::kLeft_Align,
636 kFontHeight, text_bounds.left(), text_bounds.bottom());
637 DrawText(canvas,
638 &paint,
639 value_text,
640 SkPaint::kLeft_Align,
641 kFontHeight,
642 text_bounds2.left(),
643 text_bounds2.bottom());
644 DrawText(canvas,
645 &paint,
646 min_max_text,
647 SkPaint::kRight_Align,
648 kFontHeight,
649 text_bounds2.right(),
650 text_bounds2.bottom());
652 paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
653 for (PaintTimeCounter::RingBufferType::Iterator it =
654 paint_time_counter->End();
656 --it) {
657 double pt = it->InMillisecondsF();
659 if (pt == 0.0)
660 continue;
662 double p = pt / paint_time_graph_.current_upper_bound;
663 if (p > 1.0)
664 p = 1.0;
666 canvas->drawRect(
667 SkRect::MakeXYWH(graph_bounds.left() + it.index(),
668 graph_bounds.bottom() - p * graph_bounds.height(),
670 p * graph_bounds.height()),
671 paint);
674 DrawGraphLines(canvas, &paint, graph_bounds, paint_time_graph_);
676 return area;
679 void HeadsUpDisplayLayerImpl::DrawDebugRect(
680 SkCanvas* canvas,
681 SkPaint* paint,
682 const DebugRect& rect,
683 SkColor stroke_color,
684 SkColor fill_color,
685 float stroke_width,
686 const std::string& label_text) const {
687 gfx::Rect debug_layer_rect =
688 gfx::ScaleToEnclosingRect(rect.rect, 1.0 / internal_contents_scale_,
689 1.0 / internal_contents_scale_);
690 SkIRect sk_rect = RectToSkIRect(debug_layer_rect);
691 paint->setColor(fill_color);
692 paint->setStyle(SkPaint::kFill_Style);
693 canvas->drawIRect(sk_rect, *paint);
695 paint->setColor(stroke_color);
696 paint->setStyle(SkPaint::kStroke_Style);
697 paint->setStrokeWidth(SkFloatToScalar(stroke_width));
698 canvas->drawIRect(sk_rect, *paint);
700 if (label_text.length()) {
701 const int kFontHeight = 12;
702 const int kPadding = 3;
704 // The debug_layer_rect may be huge, and converting to a floating point may
705 // be lossy, so intersect with the HUD layer bounds first to prevent that.
706 gfx::Rect clip_rect = debug_layer_rect;
707 clip_rect.Intersect(gfx::Rect(internal_content_bounds_));
708 SkRect sk_clip_rect = RectToSkRect(clip_rect);
710 canvas->save();
711 canvas->clipRect(sk_clip_rect);
712 canvas->translate(sk_clip_rect.x(), sk_clip_rect.y());
714 SkPaint label_paint = CreatePaint();
715 label_paint.setTextSize(kFontHeight);
716 label_paint.setTypeface(typeface_.get());
717 label_paint.setColor(stroke_color);
719 const SkScalar label_text_width =
720 label_paint.measureText(label_text.c_str(), label_text.length());
721 canvas->drawRect(SkRect::MakeWH(label_text_width + 2 * kPadding,
722 kFontHeight + 2 * kPadding),
723 label_paint);
725 label_paint.setAntiAlias(true);
726 label_paint.setColor(SkColorSetARGB(255, 50, 50, 50));
727 canvas->drawText(label_text.c_str(),
728 label_text.length(),
729 kPadding,
730 kFontHeight * 0.8f + kPadding,
731 label_paint);
733 canvas->restore();
737 void HeadsUpDisplayLayerImpl::DrawDebugRects(
738 SkCanvas* canvas,
739 DebugRectHistory* debug_rect_history) {
740 SkPaint paint = CreatePaint();
742 const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects();
743 std::vector<DebugRect> new_paint_rects;
745 for (size_t i = 0; i < debug_rects.size(); ++i) {
746 SkColor stroke_color = 0;
747 SkColor fill_color = 0;
748 float stroke_width = 0.f;
749 std::string label_text;
751 switch (debug_rects[i].type) {
752 case PAINT_RECT_TYPE:
753 new_paint_rects.push_back(debug_rects[i]);
754 continue;
755 case PROPERTY_CHANGED_RECT_TYPE:
756 stroke_color = DebugColors::PropertyChangedRectBorderColor();
757 fill_color = DebugColors::PropertyChangedRectFillColor();
758 stroke_width = DebugColors::PropertyChangedRectBorderWidth();
759 break;
760 case SURFACE_DAMAGE_RECT_TYPE:
761 stroke_color = DebugColors::SurfaceDamageRectBorderColor();
762 fill_color = DebugColors::SurfaceDamageRectFillColor();
763 stroke_width = DebugColors::SurfaceDamageRectBorderWidth();
764 break;
765 case REPLICA_SCREEN_SPACE_RECT_TYPE:
766 stroke_color = DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor();
767 fill_color = DebugColors::ScreenSpaceSurfaceReplicaRectFillColor();
768 stroke_width = DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth();
769 break;
770 case SCREEN_SPACE_RECT_TYPE:
771 stroke_color = DebugColors::ScreenSpaceLayerRectBorderColor();
772 fill_color = DebugColors::ScreenSpaceLayerRectFillColor();
773 stroke_width = DebugColors::ScreenSpaceLayerRectBorderWidth();
774 break;
775 case TOUCH_EVENT_HANDLER_RECT_TYPE:
776 stroke_color = DebugColors::TouchEventHandlerRectBorderColor();
777 fill_color = DebugColors::TouchEventHandlerRectFillColor();
778 stroke_width = DebugColors::TouchEventHandlerRectBorderWidth();
779 label_text = "touch event listener";
780 break;
781 case WHEEL_EVENT_HANDLER_RECT_TYPE:
782 stroke_color = DebugColors::WheelEventHandlerRectBorderColor();
783 fill_color = DebugColors::WheelEventHandlerRectFillColor();
784 stroke_width = DebugColors::WheelEventHandlerRectBorderWidth();
785 label_text = "mousewheel event listener";
786 break;
787 case SCROLL_EVENT_HANDLER_RECT_TYPE:
788 stroke_color = DebugColors::ScrollEventHandlerRectBorderColor();
789 fill_color = DebugColors::ScrollEventHandlerRectFillColor();
790 stroke_width = DebugColors::ScrollEventHandlerRectBorderWidth();
791 label_text = "scroll event listener";
792 break;
793 case NON_FAST_SCROLLABLE_RECT_TYPE:
794 stroke_color = DebugColors::NonFastScrollableRectBorderColor();
795 fill_color = DebugColors::NonFastScrollableRectFillColor();
796 stroke_width = DebugColors::NonFastScrollableRectBorderWidth();
797 label_text = "repaints on scroll";
798 break;
799 case ANIMATION_BOUNDS_RECT_TYPE:
800 stroke_color = DebugColors::LayerAnimationBoundsBorderColor();
801 fill_color = DebugColors::LayerAnimationBoundsFillColor();
802 stroke_width = DebugColors::LayerAnimationBoundsBorderWidth();
803 label_text = "animation bounds";
804 break;
807 DrawDebugRect(canvas,
808 &paint,
809 debug_rects[i],
810 stroke_color,
811 fill_color,
812 stroke_width,
813 label_text);
816 if (new_paint_rects.size()) {
817 paint_rects_.swap(new_paint_rects);
818 fade_step_ = DebugColors::kFadeSteps;
820 if (fade_step_ > 0) {
821 fade_step_--;
822 for (size_t i = 0; i < paint_rects_.size(); ++i) {
823 DrawDebugRect(canvas,
824 &paint,
825 paint_rects_[i],
826 DebugColors::PaintRectBorderColor(fade_step_),
827 DebugColors::PaintRectFillColor(fade_step_),
828 DebugColors::PaintRectBorderWidth(),
829 "");
834 const char* HeadsUpDisplayLayerImpl::LayerTypeAsString() const {
835 return "cc::HeadsUpDisplayLayerImpl";
838 void HeadsUpDisplayLayerImpl::AsValueInto(
839 base::trace_event::TracedValue* dict) const {
840 LayerImpl::AsValueInto(dict);
841 dict->SetString("layer_name", "Heads Up Display Layer");
844 } // namespace cc