heads_up_display_layer_impl.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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. 4 5#include "cc/layers/heads_up_display_layer_impl.h" 6 7#include <algorithm> 8#include <vector> 9 10#include "base/stringprintf.h" 11#include "base/strings/string_split.h" 12#include "cc/debug/debug_colors.h" 13#include "cc/debug/debug_rect_history.h" 14#include "cc/debug/frame_rate_counter.h" 15#include "cc/debug/paint_time_counter.h" 16#include "cc/layers/quad_sink.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/resources/tile_manager.h" 21#include "cc/trees/layer_tree_impl.h" 22#include "skia/ext/platform_canvas.h" 23#include "third_party/khronos/GLES2/gl2.h" 24#include "third_party/khronos/GLES2/gl2ext.h" 25#include "third_party/skia/include/core/SkBitmap.h" 26#include "third_party/skia/include/core/SkPaint.h" 27#include "third_party/skia/include/core/SkTypeface.h" 28#include "third_party/skia/include/effects/SkColorMatrixFilter.h" 29#include "ui/gfx/point.h" 30#include "ui/gfx/size.h" 31 32namespace cc { 33 34static inline SkPaint CreatePaint() { 35 SkPaint paint; 36#if (SK_R32_SHIFT || SK_B32_SHIFT != 16) 37 // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to 38 // swizzle our colors when drawing to the SkCanvas. 39 SkColorMatrix swizzle_matrix; 40 for (int i = 0; i < 20; ++i) 41 swizzle_matrix.fMat[i] = 0; 42 swizzle_matrix.fMat[0 + 5 * 2] = 1; 43 swizzle_matrix.fMat[1 + 5 * 1] = 1; 44 swizzle_matrix.fMat[2 + 5 * 0] = 1; 45 swizzle_matrix.fMat[3 + 5 * 3] = 1; 46 47 skia::RefPtr<SkColorMatrixFilter> filter = 48 skia::AdoptRef(new SkColorMatrixFilter(swizzle_matrix)); 49 paint.setColorFilter(filter.get()); 50#endif 51 return paint; 52} 53 54HeadsUpDisplayLayerImpl::Graph::Graph(double indicator_value, 55 double start_upper_bound) 56 : value(0.0), 57 min(0.0), 58 max(0.0), 59 current_upper_bound(start_upper_bound), 60 default_upper_bound(start_upper_bound), 61 indicator(indicator_value) {} 62 63double HeadsUpDisplayLayerImpl::Graph::UpdateUpperBound() { 64 double target_upper_bound = std::max(max, default_upper_bound); 65 current_upper_bound += (target_upper_bound - current_upper_bound) * 0.5; 66 return current_upper_bound; 67} 68 69HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl* tree_impl, 70 int id) 71 : LayerImpl(tree_impl, id), 72 typeface_(skia::AdoptRef( 73 SkTypeface::CreateFromName("monospace", SkTypeface::kBold))), 74 fps_graph_(60.0, 80.0), 75 paint_time_graph_(16.0, 48.0) {} 76 77HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl() {} 78 79scoped_ptr<LayerImpl> HeadsUpDisplayLayerImpl::CreateLayerImpl( 80 LayerTreeImpl* tree_impl) { 81 return HeadsUpDisplayLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 82} 83 84void HeadsUpDisplayLayerImpl::WillDraw(ResourceProvider* resource_provider) { 85 LayerImpl::WillDraw(resource_provider); 86 87 if (!hud_resource_) 88 hud_resource_ = ScopedResource::create(resource_provider); 89 90 // TODO(danakj): Scale the HUD by device scale to make it more friendly under 91 // high DPI. 92 93 // TODO(danakj): The HUD could swap between two textures instead of creating a 94 // texture every frame in ubercompositor. 95 if (hud_resource_->size() != bounds() || 96 resource_provider->InUseByConsumer(hud_resource_->id())) 97 hud_resource_->Free(); 98 99 if (!hud_resource_->id()) { 100 hud_resource_->Allocate( 101 bounds(), GL_RGBA, ResourceProvider::TextureUsageAny); 102 } 103} 104 105void HeadsUpDisplayLayerImpl::AppendQuads(QuadSink* quad_sink, 106 AppendQuadsData* append_quads_data) { 107 if (!hud_resource_->id()) 108 return; 109 110 SharedQuadState* shared_quad_state = 111 quad_sink->UseSharedQuadState(CreateSharedQuadState()); 112 113 gfx::Rect quad_rect(bounds()); 114 gfx::Rect opaque_rect(contents_opaque() ? quad_rect : gfx::Rect()); 115 bool premultiplied_alpha = true; 116 gfx::PointF uv_top_left(0.f, 0.f); 117 gfx::PointF uv_bottom_right(1.f, 1.f); 118 const float vertex_opacity[] = { 1.f, 1.f, 1.f, 1.f }; 119 bool flipped = false; 120 scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); 121 quad->SetNew(shared_quad_state, 122 quad_rect, 123 opaque_rect, 124 hud_resource_->id(), 125 premultiplied_alpha, 126 uv_top_left, 127 uv_bottom_right, 128 vertex_opacity, 129 flipped); 130 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); 131} 132 133void HeadsUpDisplayLayerImpl::UpdateHudTexture( 134 ResourceProvider* resource_provider) { 135 if (!hud_resource_->id()) 136 return; 137 138 SkISize canvas_size; 139 if (hud_canvas_) 140 canvas_size = hud_canvas_->getDeviceSize(); 141 else 142 canvas_size.set(0, 0); 143 144 if (canvas_size.fWidth != bounds().width() || 145 canvas_size.fHeight != bounds().height() || !hud_canvas_) { 146 bool opaque = false; 147 hud_canvas_ = make_scoped_ptr( 148 skia::CreateBitmapCanvas(bounds().width(), bounds().height(), opaque)); 149 } 150 151 UpdateHudContents(); 152 153 hud_canvas_->clear(SkColorSetARGB(0, 0, 0, 0)); 154 DrawHudContents(hud_canvas_.get()); 155 156 const SkBitmap* bitmap = &hud_canvas_->getDevice()->accessBitmap(false); 157 SkAutoLockPixels locker(*bitmap); 158 159 gfx::Rect layer_rect(bounds()); 160 DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config); 161 resource_provider->SetPixels(hud_resource_->id(), 162 static_cast<const uint8_t*>(bitmap->getPixels()), 163 layer_rect, 164 layer_rect, 165 gfx::Vector2d()); 166} 167 168void HeadsUpDisplayLayerImpl::DidDraw(ResourceProvider* resource_provider) { 169 LayerImpl::DidDraw(resource_provider); 170 171 if (!hud_resource_->id()) 172 return; 173 174 // FIXME: the following assert will not be true when sending resources to a 175 // parent compositor. We will probably need to hold on to hud_resource_ for 176 // longer, and have several HUD textures in the pipeline. 177 DCHECK(!resource_provider->InUseByConsumer(hud_resource_->id())); 178} 179 180void HeadsUpDisplayLayerImpl::DidLoseOutputSurface() { hud_resource_.reset(); } 181 182bool HeadsUpDisplayLayerImpl::LayerIsAlwaysDamaged() const { return true; } 183 184void HeadsUpDisplayLayerImpl::UpdateHudContents() { 185 const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state(); 186 187 // Don't update numbers every frame so text is readable. 188 base::TimeTicks now = layer_tree_impl()->CurrentFrameTimeTicks(); 189 if (base::TimeDelta(now - time_of_last_graph_update_).InSecondsF() > 0.25f) { 190 time_of_last_graph_update_ = now; 191 192 if (debug_state.show_fps_counter) { 193 FrameRateCounter* fps_counter = layer_tree_impl()->frame_rate_counter(); 194 fps_graph_.value = fps_counter->GetAverageFPS(); 195 fps_counter->GetMinAndMaxFPS(&fps_graph_.min, &fps_graph_.max); 196 } 197 198 if (debug_state.continuous_painting) { 199 PaintTimeCounter* paint_time_counter = 200 layer_tree_impl()->paint_time_counter(); 201 base::TimeDelta latest, min, max; 202 203 if (paint_time_counter->End()) 204 latest = **paint_time_counter->End(); 205 paint_time_counter->GetMinAndMaxPaintTime(&min, &max); 206 207 paint_time_graph_.value = latest.InMillisecondsF(); 208 paint_time_graph_.min = min.InMillisecondsF(); 209 paint_time_graph_.max = max.InMillisecondsF(); 210 } 211 212 if (debug_state.ShowMemoryStats()) { 213 MemoryHistory* memory_history = layer_tree_impl()->memory_history(); 214 if (memory_history->End()) 215 memory_entry_ = **memory_history->End(); 216 else 217 memory_entry_ = MemoryHistory::Entry(); 218 } 219 } 220 221 fps_graph_.UpdateUpperBound(); 222 paint_time_graph_.UpdateUpperBound(); 223} 224 225void HeadsUpDisplayLayerImpl::DrawHudContents(SkCanvas* canvas) const { 226 const LayerTreeDebugState& debug_state = layer_tree_impl()->debug_state(); 227 228 if (debug_state.ShowHudRects()) 229 DrawDebugRects(canvas, layer_tree_impl()->debug_rect_history()); 230 231 if (debug_state.show_platform_layer_tree) 232 DrawPlatformLayerTree(canvas); 233 234 SkRect area = SkRect::MakeEmpty(); 235 if (debug_state.continuous_painting) { 236 // Don't show the FPS display when continuous painting is enabled, because 237 // it would show misleading numbers. 238 area = DrawPaintTimeDisplay( 239 canvas, layer_tree_impl()->paint_time_counter(), 0, 0); 240 } else if (debug_state.show_fps_counter) { 241 area = 242 DrawFPSDisplay(canvas, layer_tree_impl()->frame_rate_counter(), 0, 0); 243 } 244 245 if (debug_state.ShowMemoryStats()) 246 DrawMemoryDisplay(canvas, 0, area.bottom(), SkMaxScalar(area.width(), 150)); 247} 248 249void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas, 250 SkPaint* paint, 251 const std::string& text, 252 SkPaint::Align align, 253 int size, 254 int x, 255 int y) const { 256 const bool anti_alias = paint->isAntiAlias(); 257 paint->setAntiAlias(true); 258 259 paint->setTextSize(size); 260 paint->setTextAlign(align); 261 paint->setTypeface(typeface_.get()); 262 canvas->drawText(text.c_str(), text.length(), x, y, *paint); 263 264 paint->setAntiAlias(anti_alias); 265} 266 267void HeadsUpDisplayLayerImpl::DrawText(SkCanvas* canvas, 268 SkPaint* paint, 269 const std::string& text, 270 SkPaint::Align align, 271 int size, 272 const SkPoint& pos) const { 273 DrawText(canvas, paint, text, align, size, pos.x(), pos.y()); 274} 275 276void HeadsUpDisplayLayerImpl::DrawGraphBackground(SkCanvas* canvas, 277 SkPaint* paint, 278 const SkRect& bounds) const { 279 paint->setColor(DebugColors::HUDBackgroundColor()); 280 canvas->drawRect(bounds, *paint); 281} 282 283void HeadsUpDisplayLayerImpl::DrawGraphLines(SkCanvas* canvas, 284 SkPaint* paint, 285 const SkRect& bounds, 286 const Graph& graph) const { 287 // Draw top and bottom line. 288 paint->setColor(DebugColors::HUDSeparatorLineColor()); 289 canvas->drawLine(bounds.left(), 290 bounds.top() - 1, 291 bounds.right(), 292 bounds.top() - 1, 293 *paint); 294 canvas->drawLine( 295 bounds.left(), bounds.bottom(), bounds.right(), bounds.bottom(), *paint); 296 297 // Draw indicator line (additive blend mode to increase contrast when drawn on 298 // top of graph). 299 paint->setColor(DebugColors::HUDIndicatorLineColor()); 300 paint->setXfermodeMode(SkXfermode::kPlus_Mode); 301 const double indicator_top = 302 bounds.height() * (1.0 - graph.indicator / graph.current_upper_bound) - 303 1.0; 304 canvas->drawLine(bounds.left(), 305 bounds.top() + indicator_top, 306 bounds.right(), 307 bounds.top() + indicator_top, 308 *paint); 309 paint->setXfermode(NULL); 310} 311 312void HeadsUpDisplayLayerImpl::DrawPlatformLayerTree(SkCanvas* canvas) const { 313 const int kFontHeight = 14; 314 SkPaint paint = CreatePaint(); 315 DrawGraphBackground( 316 canvas, 317 &paint, 318 SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height())); 319 320 std::string layer_tree = layer_tree_impl()->layer_tree_as_text(); 321 std::vector<std::string> lines; 322 base::SplitString(layer_tree, '\n', &lines); 323 324 paint.setColor(DebugColors::PlatformLayerTreeTextColor()); 325 for (size_t i = 0; 326 i < lines.size() && 327 static_cast<int>(2 + i * kFontHeight) < bounds().height(); 328 ++i) { 329 DrawText(canvas, 330 &paint, 331 lines[i], 332 SkPaint::kLeft_Align, 333 kFontHeight, 334 2, 335 2 + (i + 1) * kFontHeight); 336 } 337} 338 339SkRect HeadsUpDisplayLayerImpl::DrawFPSDisplay( 340 SkCanvas* canvas, 341 const FrameRateCounter* fps_counter, 342 int right, 343 int top) const { 344 const int kPadding = 4; 345 const int kGap = 6; 346 347 const int kFontHeight = 15; 348 349 const int kGraphWidth = fps_counter->time_stamp_history_size() - 2; 350 const int kGraphHeight = 40; 351 352 const int kHistogramWidth = 37; 353 354 int width = kGraphWidth + kHistogramWidth + 4 * kPadding; 355 int height = kFontHeight + kGraphHeight + 4 * kPadding + 2; 356 int left = bounds().width() - width - right; 357 SkRect area = SkRect::MakeXYWH(left, top, width, height); 358 359 SkPaint paint = CreatePaint(); 360 DrawGraphBackground(canvas, &paint, area); 361 362 SkRect text_bounds = 363 SkRect::MakeXYWH(left + kPadding, 364 top + kPadding, 365 kGraphWidth + kHistogramWidth + kGap + 2, 366 kFontHeight); 367 SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding, 368 text_bounds.bottom() + 2 * kPadding, 369 kGraphWidth, 370 kGraphHeight); 371 SkRect histogram_bounds = SkRect::MakeXYWH(graph_bounds.right() + kGap, 372 graph_bounds.top(), 373 kHistogramWidth, 374 kGraphHeight); 375 376 const std::string value_text = 377 base::StringPrintf("FPS:%5.1f", fps_graph_.value); 378 const std::string min_max_text = 379 base::StringPrintf("%.0f-%.0f", fps_graph_.min, fps_graph_.max); 380 381 paint.setColor(DebugColors::FPSDisplayTextAndGraphColor()); 382 DrawText(canvas, 383 &paint, 384 value_text, 385 SkPaint::kLeft_Align, 386 kFontHeight, 387 text_bounds.left(), 388 text_bounds.bottom()); 389 DrawText(canvas, 390 &paint, 391 min_max_text, 392 SkPaint::kRight_Align, 393 kFontHeight, 394 text_bounds.right(), 395 text_bounds.bottom()); 396 397 DrawGraphLines(canvas, &paint, graph_bounds, fps_graph_); 398 399 // Collect graph and histogram data. 400 SkPath path; 401 402 const int kHistogramSize = 20; 403 double histogram[kHistogramSize] = { 1.0 }; 404 double max_bucket_value = 1.0; 405 406 for (FrameRateCounter::RingBufferType::Iterator it = --fps_counter->end(); it; 407 --it) { 408 base::TimeDelta delta = fps_counter->RecentFrameInterval(it.index() + 1); 409 410 // Skip this particular instantaneous frame rate if it is not likely to have 411 // been valid. 412 if (!fps_counter->IsBadFrameInterval(delta)) { 413 double fps = 1.0 / delta.InSecondsF(); 414 415 // Clamp the FPS to the range we want to plot visually. 416 double p = fps / fps_graph_.current_upper_bound; 417 if (p > 1.0) 418 p = 1.0; 419 420 // Plot this data point. 421 SkPoint cur = 422 SkPoint::Make(graph_bounds.left() + it.index(), 423 graph_bounds.bottom() - p * graph_bounds.height()); 424 if (path.isEmpty()) 425 path.moveTo(cur); 426 else 427 path.lineTo(cur); 428 429 // Use the fps value to find the right bucket in the histogram. 430 int bucket_index = floor(p * (kHistogramSize - 1)); 431 432 // Add the delta time to take the time spent at that fps rate into 433 // account. 434 histogram[bucket_index] += delta.InSecondsF(); 435 max_bucket_value = std::max(histogram[bucket_index], max_bucket_value); 436 } 437 } 438 439 // Draw FPS histogram. 440 paint.setColor(DebugColors::HUDSeparatorLineColor()); 441 canvas->drawLine(histogram_bounds.left() - 1, 442 histogram_bounds.top() - 1, 443 histogram_bounds.left() - 1, 444 histogram_bounds.bottom() + 1, 445 paint); 446 canvas->drawLine(histogram_bounds.right() + 1, 447 histogram_bounds.top() - 1, 448 histogram_bounds.right() + 1, 449 histogram_bounds.bottom() + 1, 450 paint); 451 452 paint.setColor(DebugColors::FPSDisplayTextAndGraphColor()); 453 const double bar_height = histogram_bounds.height() / kHistogramSize; 454 455 for (int i = kHistogramSize - 1; i >= 0; --i) { 456 if (histogram[i] > 0) { 457 double bar_width = 458 histogram[i] / max_bucket_value * histogram_bounds.width(); 459 canvas->drawRect( 460 SkRect::MakeXYWH(histogram_bounds.left(), 461 histogram_bounds.bottom() - (i + 1) * bar_height, 462 bar_width, 463 1), 464 paint); 465 } 466 } 467 468 // Draw FPS graph. 469 paint.setAntiAlias(true); 470 paint.setStyle(SkPaint::kStroke_Style); 471 paint.setStrokeWidth(1); 472 canvas->drawPath(path, paint); 473 474 return area; 475} 476 477SkRect HeadsUpDisplayLayerImpl::DrawMemoryDisplay(SkCanvas* canvas, 478 int right, 479 int top, 480 int width) const { 481 if (!memory_entry_.bytes_total()) 482 return SkRect::MakeEmpty(); 483 484 const int kPadding = 4; 485 const int kFontHeight = 13; 486 487 const int height = 3 * kFontHeight + 4 * kPadding; 488 const int left = bounds().width() - width - right; 489 const SkRect area = SkRect::MakeXYWH(left, top, width, height); 490 491 const double megabyte = 1024.0 * 1024.0; 492 493 SkPaint paint = CreatePaint(); 494 DrawGraphBackground(canvas, &paint, area); 495 496 SkPoint title_pos = SkPoint::Make(left + kPadding, top + kFontHeight); 497 SkPoint stat1_pos = SkPoint::Make(left + width - kPadding - 1, 498 top + kPadding + 2 * kFontHeight); 499 SkPoint stat2_pos = SkPoint::Make(left + width - kPadding - 1, 500 top + 2 * kPadding + 3 * kFontHeight); 501 502 paint.setColor(DebugColors::MemoryDisplayTextColor()); 503 DrawText(canvas, 504 &paint, 505 "GPU memory", 506 SkPaint::kLeft_Align, 507 kFontHeight, 508 title_pos); 509 510 std::string text = 511 base::StringPrintf("%6.1f MB used", 512 (memory_entry_.bytes_unreleasable + 513 memory_entry_.bytes_allocated) / megabyte); 514 DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat1_pos); 515 516 if (memory_entry_.bytes_over) { 517 paint.setColor(SK_ColorRED); 518 text = base::StringPrintf("%6.1f MB over", 519 memory_entry_.bytes_over / megabyte); 520 } else { 521 text = base::StringPrintf("%6.1f MB max ", 522 memory_entry_.total_budget_in_bytes / megabyte); 523 } 524 DrawText(canvas, &paint, text, SkPaint::kRight_Align, kFontHeight, stat2_pos); 525 526 return area; 527} 528 529SkRect HeadsUpDisplayLayerImpl::DrawPaintTimeDisplay( 530 SkCanvas* canvas, 531 const PaintTimeCounter* paint_time_counter, 532 int right, 533 int top) const { 534 const int kPadding = 4; 535 const int kFontHeight = 15; 536 537 const int kGraphWidth = paint_time_counter->HistorySize(); 538 const int kGraphHeight = 40; 539 540 const int width = kGraphWidth + 2 * kPadding; 541 const int height = 542 kFontHeight + kGraphHeight + 4 * kPadding + 2 + kFontHeight + kPadding; 543 const int left = bounds().width() - width - right; 544 545 const SkRect area = SkRect::MakeXYWH(left, top, width, height); 546 547 SkPaint paint = CreatePaint(); 548 DrawGraphBackground(canvas, &paint, area); 549 550 SkRect text_bounds = SkRect::MakeXYWH( 551 left + kPadding, top + kPadding, kGraphWidth, kFontHeight); 552 SkRect text_bounds2 = SkRect::MakeXYWH(left + kPadding, 553 text_bounds.bottom() + kPadding, 554 kGraphWidth, 555 kFontHeight); 556 SkRect graph_bounds = SkRect::MakeXYWH(left + kPadding, 557 text_bounds2.bottom() + 2 * kPadding, 558 kGraphWidth, 559 kGraphHeight); 560 561 const std::string value_text = 562 base::StringPrintf("%.1f", paint_time_graph_.value); 563 const std::string min_max_text = base::StringPrintf( 564 "%.1f-%.1f", paint_time_graph_.min, paint_time_graph_.max); 565 566 paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor()); 567 DrawText(canvas, 568 &paint, 569 "Page paint time (ms)", 570 SkPaint::kLeft_Align, 571 kFontHeight, 572 text_bounds.left(), 573 text_bounds.bottom()); 574 DrawText(canvas, 575 &paint, 576 value_text, 577 SkPaint::kLeft_Align, 578 kFontHeight, 579 text_bounds2.left(), 580 text_bounds2.bottom()); 581 DrawText(canvas, 582 &paint, 583 min_max_text, 584 SkPaint::kRight_Align, 585 kFontHeight, 586 text_bounds2.right(), 587 text_bounds2.bottom()); 588 589 paint.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor()); 590 for (PaintTimeCounter::RingBufferType::Iterator it = 591 paint_time_counter->End(); 592 it; 593 --it) { 594 double pt = it->InMillisecondsF(); 595 596 if (pt == 0.0) 597 continue; 598 599 double p = pt / paint_time_graph_.current_upper_bound; 600 if (p > 1.0) 601 p = 1.0; 602 603 canvas->drawRect( 604 SkRect::MakeXYWH(graph_bounds.left() + it.index(), 605 graph_bounds.bottom() - p * graph_bounds.height(), 606 1, 607 p * graph_bounds.height()), 608 paint); 609 } 610 611 DrawGraphLines(canvas, &paint, graph_bounds, paint_time_graph_); 612 613 return area; 614} 615 616void HeadsUpDisplayLayerImpl::DrawDebugRects( 617 SkCanvas* canvas, 618 DebugRectHistory* debug_rect_history) const { 619 const std::vector<DebugRect>& debug_rects = debug_rect_history->debug_rects(); 620 float rect_scale = 1.f / layer_tree_impl()->device_scale_factor(); 621 SkPaint paint = CreatePaint(); 622 623 canvas->save(); 624 canvas->scale(rect_scale, rect_scale); 625 626 for (size_t i = 0; i < debug_rects.size(); ++i) { 627 SkColor stroke_color = 0; 628 SkColor fill_color = 0; 629 float stroke_width = 0.f; 630 631 switch (debug_rects[i].type) { 632 case PAINT_RECT_TYPE: 633 stroke_color = DebugColors::PaintRectBorderColor(); 634 fill_color = DebugColors::PaintRectFillColor(); 635 stroke_width = DebugColors::PaintRectBorderWidth(layer_tree_impl()); 636 break; 637 case PROPERTY_CHANGED_RECT_TYPE: 638 stroke_color = DebugColors::PropertyChangedRectBorderColor(); 639 fill_color = DebugColors::PropertyChangedRectFillColor(); 640 stroke_width = 641 DebugColors::PropertyChangedRectBorderWidth(layer_tree_impl()); 642 break; 643 case SURFACE_DAMAGE_RECT_TYPE: 644 stroke_color = DebugColors::SurfaceDamageRectBorderColor(); 645 fill_color = DebugColors::SurfaceDamageRectFillColor(); 646 stroke_width = 647 DebugColors::SurfaceDamageRectBorderWidth(layer_tree_impl()); 648 break; 649 case REPLICA_SCREEN_SPACE_RECT_TYPE: 650 stroke_color = DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor(); 651 fill_color = DebugColors::ScreenSpaceSurfaceReplicaRectFillColor(); 652 stroke_width = DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth( 653 layer_tree_impl()); 654 break; 655 case SCREEN_SPACE_RECT_TYPE: 656 stroke_color = DebugColors::ScreenSpaceLayerRectBorderColor(); 657 fill_color = DebugColors::ScreenSpaceLayerRectFillColor(); 658 stroke_width = 659 DebugColors::ScreenSpaceLayerRectBorderWidth(layer_tree_impl()); 660 break; 661 case OCCLUDING_RECT_TYPE: 662 stroke_color = DebugColors::OccludingRectBorderColor(); 663 fill_color = DebugColors::OccludingRectFillColor(); 664 stroke_width = DebugColors::OccludingRectBorderWidth(layer_tree_impl()); 665 break; 666 case NONOCCLUDING_RECT_TYPE: 667 stroke_color = DebugColors::NonOccludingRectBorderColor(); 668 fill_color = DebugColors::NonOccludingRectFillColor(); 669 stroke_width = 670 DebugColors::NonOccludingRectBorderWidth(layer_tree_impl()); 671 break; 672 } 673 674 const gfx::RectF& rect = debug_rects[i].rect; 675 SkRect sk_rect = 676 SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height()); 677 paint.setColor(fill_color); 678 paint.setStyle(SkPaint::kFill_Style); 679 canvas->drawRect(sk_rect, paint); 680 681 paint.setColor(stroke_color); 682 paint.setStyle(SkPaint::kStroke_Style); 683 paint.setStrokeWidth(SkFloatToScalar(stroke_width)); 684 canvas->drawRect(sk_rect, paint); 685 } 686 687 canvas->restore(); 688} 689 690const char* HeadsUpDisplayLayerImpl::LayerTypeAsString() const { 691 return "HeadsUpDisplayLayer"; 692} 693 694} // namespace cc 695