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