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/heads_up_display_layer_impl.h"
7 #include "base/string_split.h"
8 #include "base/stringprintf.h"
9 #include "cc/debug_colors.h"
10 #include "cc/debug_rect_history.h"
11 #include "cc/frame_rate_counter.h"
12 #include "cc/layer_tree_impl.h"
13 #include "cc/memory_history.h"
14 #include "cc/paint_time_counter.h"
15 #include "cc/quad_sink.h"
16 #include "cc/renderer.h"
17 #include "cc/texture_draw_quad.h"
18 #include "cc/tile_manager.h"
19 #include "skia/ext/platform_canvas.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/SkFontHost.h"
25 #include "third_party/skia/include/core/SkPaint.h"
26 #include "third_party/skia/include/core/SkTypeface.h"
27 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
28 #include "ui/gfx/point.h"
29 #include "ui/gfx/size.h"
33 static inline SkPaint
createPaint()
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 swizzleMatrix
;
40 for (int i
= 0; i
< 20; ++i
)
41 swizzleMatrix
.fMat
[i
] = 0;
42 swizzleMatrix
.fMat
[0 + 5 * 2] = 1;
43 swizzleMatrix
.fMat
[1 + 5 * 1] = 1;
44 swizzleMatrix
.fMat
[2 + 5 * 0] = 1;
45 swizzleMatrix
.fMat
[3 + 5 * 3] = 1;
47 skia::RefPtr
<SkColorMatrixFilter
> filter
=
48 skia::AdoptRef(new SkColorMatrixFilter(swizzleMatrix
));
49 paint
.setColorFilter(filter
.get());
54 HeadsUpDisplayLayerImpl::Graph::Graph(double indicatorValue
, double startUpperBound
)
58 , currentUpperBound(startUpperBound
)
59 , defaultUpperBound(startUpperBound
)
60 , indicator(indicatorValue
)
64 double HeadsUpDisplayLayerImpl::Graph::updateUpperBound(Graph
* graph
)
66 double targetUpperBound
= std::max(graph
->max
, graph
->defaultUpperBound
);
67 graph
->currentUpperBound
+= (targetUpperBound
- graph
->currentUpperBound
) * 0.5;
68 return graph
->currentUpperBound
;
71 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeImpl
* treeImpl
, int id
)
72 : LayerImpl(treeImpl
, id
)
73 , m_fpsGraph(60.0, 80.0)
74 , m_paintTimeGraph(16.0, 48.0)
75 , m_typeface(skia::AdoptRef(SkFontHost::CreateTypeface(NULL
, "monospace", SkTypeface::kBold
)))
79 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl()
83 scoped_ptr
<LayerImpl
> HeadsUpDisplayLayerImpl::createLayerImpl(LayerTreeImpl
* treeImpl
)
85 return HeadsUpDisplayLayerImpl::create(treeImpl
, id()).PassAs
<LayerImpl
>();
88 void HeadsUpDisplayLayerImpl::willDraw(ResourceProvider
* resourceProvider
)
90 LayerImpl::willDraw(resourceProvider
);
93 m_hudTexture
= ScopedResource::create(resourceProvider
);
95 // TODO(danakj): Scale the HUD by deviceScale to make it more friendly under high DPI.
97 // TODO(danakj): The HUD could swap between two textures instead of creating a texture every frame in ubercompositor.
98 if (m_hudTexture
->size() != bounds() || resourceProvider
->inUseByConsumer(m_hudTexture
->id()))
101 if (!m_hudTexture
->id()) {
102 m_hudTexture
->Allocate(bounds(), GL_RGBA
, ResourceProvider::TextureUsageAny
);
103 // TODO(epenner): This texture was being used before setPixels was called,
104 // which is now not allowed (it's an uninitialized read). This should be fixed
105 // and this allocateForTesting() removed.
106 // http://crbug.com/166784
107 resourceProvider
->allocateForTesting(m_hudTexture
->id());
111 void HeadsUpDisplayLayerImpl::appendQuads(QuadSink
& quadSink
, AppendQuadsData
& appendQuadsData
)
113 if (!m_hudTexture
->id())
116 SharedQuadState
* sharedQuadState
= quadSink
.useSharedQuadState(createSharedQuadState());
118 gfx::Rect
quadRect(gfx::Point(), bounds());
119 gfx::Rect
opaqueRect(contentsOpaque() ? quadRect
: gfx::Rect());
120 bool premultipliedAlpha
= true;
121 gfx::PointF
uv_top_left(0.f
, 0.f
);
122 gfx::PointF
uv_bottom_right(1.f
, 1.f
);
123 const float vertex_opacity
[] = {1.f
, 1.f
, 1.f
, 1.f
};
124 bool flipped
= false;
125 scoped_ptr
<TextureDrawQuad
> quad
= TextureDrawQuad::Create();
126 quad
->SetNew(sharedQuadState
, quadRect
, opaqueRect
, m_hudTexture
->id(), premultipliedAlpha
, uv_top_left
, uv_bottom_right
, vertex_opacity
, flipped
);
127 quadSink
.append(quad
.PassAs
<DrawQuad
>(), appendQuadsData
);
130 void HeadsUpDisplayLayerImpl::updateHudTexture(ResourceProvider
* resourceProvider
)
132 if (!m_hudTexture
->id())
137 canvasSize
= m_hudCanvas
->getDeviceSize();
139 canvasSize
.set(0, 0);
141 if (canvasSize
.fWidth
!= bounds().width() || canvasSize
.fHeight
!= bounds().height() || !m_hudCanvas
)
142 m_hudCanvas
= make_scoped_ptr(skia::CreateBitmapCanvas(bounds().width(), bounds().height(), false /* opaque */));
144 m_hudCanvas
->clear(SkColorSetARGB(0, 0, 0, 0));
145 drawHudContents(m_hudCanvas
.get());
147 const SkBitmap
* bitmap
= &m_hudCanvas
->getDevice()->accessBitmap(false);
148 SkAutoLockPixels
locker(*bitmap
);
150 gfx::Rect
layerRect(gfx::Point(), bounds());
151 DCHECK(bitmap
->config() == SkBitmap::kARGB_8888_Config
);
152 resourceProvider
->setPixels(m_hudTexture
->id(), static_cast<const uint8_t*>(bitmap
->getPixels()), layerRect
, layerRect
, gfx::Vector2d());
155 void HeadsUpDisplayLayerImpl::didDraw(ResourceProvider
* resourceProvider
)
157 LayerImpl::didDraw(resourceProvider
);
159 if (!m_hudTexture
->id())
162 // FIXME: the following assert will not be true when sending resources to a
163 // parent compositor. We will probably need to hold on to m_hudTexture for
164 // longer, and have several HUD textures in the pipeline.
165 DCHECK(!resourceProvider
->inUseByConsumer(m_hudTexture
->id()));
168 void HeadsUpDisplayLayerImpl::didLoseOutputSurface()
170 m_hudTexture
.reset();
173 bool HeadsUpDisplayLayerImpl::layerIsAlwaysDamaged() const
178 void HeadsUpDisplayLayerImpl::drawHudContents(SkCanvas
* canvas
)
180 const LayerTreeDebugState
& debugState
= layerTreeImpl()->debug_state();
182 if (debugState
.showPlatformLayerTree
)
183 drawPlaformLayerTree(canvas
);
185 if (debugState
.continuousPainting
|| debugState
.showFPSCounter
) {
186 FrameRateCounter
* fpsCounter
= layerTreeImpl()->frame_rate_counter();
187 PaintTimeCounter
* paintTimeCounter
= layerTreeImpl()->paint_time_counter();
189 // Update numbers not every frame so text is readable
190 base::TimeTicks now
= base::TimeTicks::Now();
191 if (base::TimeDelta(now
- m_timeOfLastGraphUpdate
).InSecondsF() > 0.25) {
192 m_fpsGraph
.value
= fpsCounter
->getAverageFPS();
193 fpsCounter
->getMinAndMaxFPS(m_fpsGraph
.min
, m_fpsGraph
.max
);
195 base::TimeDelta latest
, min
, max
;
196 if (paintTimeCounter
->End())
197 latest
= paintTimeCounter
->End()->total_time();
198 paintTimeCounter
->GetMinAndMaxPaintTime(&min
, &max
);
200 m_paintTimeGraph
.value
= latest
.InMillisecondsF();
201 m_paintTimeGraph
.min
= min
.InMillisecondsF();
202 m_paintTimeGraph
.max
= max
.InMillisecondsF();
204 m_timeOfLastGraphUpdate
= now
;
208 if (debugState
.continuousPainting
)
209 top
= drawPaintTimeDisplay(canvas
, paintTimeCounter
, top
);
210 // Don't show the FPS display when continuous painting is enabled, because it would show misleading numbers.
211 else if (debugState
.showFPSCounter
)
212 top
= drawFPSDisplay(canvas
, fpsCounter
, top
);
214 drawMemoryDisplay(canvas
, layerTreeImpl()->memory_history(), top
);
217 if (debugState
.showHudRects())
218 drawDebugRects(canvas
, layerTreeImpl()->debug_rect_history());
221 void HeadsUpDisplayLayerImpl::drawText(SkCanvas
* canvas
, SkPaint
* paint
, const std::string
& text
, const SkPaint::Align
& align
, const int& size
, const int& x
, const int& y
)
223 const bool antiAlias
= paint
->isAntiAlias();
224 paint
->setAntiAlias(true);
226 paint
->setTextSize(size
);
227 paint
->setTextAlign(align
);
228 paint
->setTypeface(m_typeface
.get());
229 canvas
->drawText(text
.c_str(), text
.length(), x
, y
, *paint
);
231 paint
->setAntiAlias(antiAlias
);
234 void HeadsUpDisplayLayerImpl::drawText(SkCanvas
* canvas
, SkPaint
* paint
, const std::string
& text
, const SkPaint::Align
& align
, const int& size
, const SkPoint
& pos
)
236 drawText(canvas
, paint
, text
, align
, size
, pos
.x(), pos
.y());
239 void HeadsUpDisplayLayerImpl::drawGraphBackground(SkCanvas
* canvas
, SkPaint
* paint
, const SkRect
& bounds
)
241 paint
->setColor(SkColorSetARGB(215, 17, 17, 17));
242 canvas
->drawRect(bounds
, *paint
);
245 void HeadsUpDisplayLayerImpl::drawGraphLines(SkCanvas
* canvas
, SkPaint
* paint
, const SkRect
& bounds
, const Graph
& graph
)
247 // Draw top and bottom line.
248 paint
->setColor(SkColorSetRGB(130, 130, 130));
249 canvas
->drawLine(bounds
.left(), bounds
.top() - 1, bounds
.right(), bounds
.top() - 1, *paint
);
250 canvas
->drawLine(bounds
.left(), bounds
.bottom(), bounds
.right(), bounds
.bottom(), *paint
);
252 // Draw indicator line.
253 paint
->setColor(SkColorSetRGB(100, 100, 100));
254 const double indicatorTop
= bounds
.height() * (1 - graph
.indicator
/ graph
.currentUpperBound
) - 1;
255 canvas
->drawLine(bounds
.left(), bounds
.top() + indicatorTop
, bounds
.right(), bounds
.top() + indicatorTop
, *paint
);
258 void HeadsUpDisplayLayerImpl::drawPlaformLayerTree(SkCanvas
* canvas
)
260 const int fontHeight
= 14;
261 SkPaint paint
= createPaint();
262 drawGraphBackground(canvas
, &paint
, SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()));
264 std::string layerTree
= layerTreeImpl()->layer_tree_as_text();
265 std::vector
<std::string
> lines
;
266 base::SplitString(layerTree
, '\n', &lines
);
268 paint
.setColor(DebugColors::PlatformLayerTreeTextColor());
269 for (size_t i
= 0; i
< lines
.size() && static_cast<int>(2 + i
* fontHeight
) < bounds().height(); ++i
) {
270 drawText(canvas
, &paint
, lines
[i
], SkPaint::kLeft_Align
, fontHeight
, 2, 2 + (i
+ 1) * fontHeight
);
274 int HeadsUpDisplayLayerImpl::drawFPSDisplay(SkCanvas
* canvas
, FrameRateCounter
* fpsCounter
, const int& top
)
276 const int padding
= 4;
279 const int fontHeight
= 15;
281 const int graphWidth
= fpsCounter
->timeStampHistorySize() - 2;
282 const int graphHeight
= 40;
284 const int histogramWidth
= 37;
286 const int width
= graphWidth
+ histogramWidth
+ 4 * padding
;
287 const int height
= fontHeight
+ graphHeight
+ 4 * padding
+ 2;
289 const int left
= bounds().width() - width
- 2;
291 SkPaint paint
= createPaint();
292 drawGraphBackground(canvas
, &paint
, SkRect::MakeXYWH(left
, top
, width
, height
));
294 SkRect textBounds
= SkRect::MakeXYWH(left
+ padding
, top
+ padding
, graphWidth
+ histogramWidth
+ gap
+ 2, fontHeight
);
295 SkRect graphBounds
= SkRect::MakeXYWH(left
+ padding
, textBounds
.bottom() + 2 * padding
, graphWidth
, graphHeight
);
296 SkRect histogramBounds
= SkRect::MakeXYWH(graphBounds
.right() + gap
, graphBounds
.top(), histogramWidth
, graphHeight
);
298 const std::string valueText
= base::StringPrintf("FPS:%5.1f", m_fpsGraph
.value
);
299 const std::string minMaxText
= base::StringPrintf("%.0f-%.0f", m_fpsGraph
.min
, m_fpsGraph
.max
);
301 paint
.setColor(DebugColors::FPSDisplayTextAndGraphColor());
302 drawText(canvas
, &paint
, valueText
, SkPaint::kLeft_Align
, fontHeight
, textBounds
.left(), textBounds
.bottom());
303 drawText(canvas
, &paint
, minMaxText
, SkPaint::kRight_Align
, fontHeight
, textBounds
.right(), textBounds
.bottom());
305 const double upperBound
= Graph::updateUpperBound(&m_fpsGraph
);
306 drawGraphLines(canvas
, &paint
, graphBounds
, m_fpsGraph
);
308 // Collect graph and histogram data.
311 const int histogramSize
= 20;
312 double histogram
[histogramSize
] = {0};
313 double maxBucketValue
= 0;
315 for (FrameRateCounter::RingBufferType::Iterator it
= --fpsCounter
->end(); it
; --it
) {
316 base::TimeDelta delta
= fpsCounter
->recentFrameInterval(it
.index() + 1);
318 // Skip this particular instantaneous frame rate if it is not likely to have been valid.
319 if (!fpsCounter
->isBadFrameInterval(delta
)) {
321 double fps
= 1.0 / delta
.InSecondsF();
323 // Clamp the FPS to the range we want to plot visually.
324 double p
= fps
/ upperBound
;
328 // Plot this data point.
329 SkPoint cur
= SkPoint::Make(graphBounds
.left() + it
.index(), graphBounds
.bottom() - p
* graphBounds
.height());
335 // Use the fps value to find the right bucket in the histogram.
336 int bucketIndex
= floor(p
* (histogramSize
- 1));
338 // Add the delta time to take the time spent at that fps rate into account.
339 histogram
[bucketIndex
] += delta
.InSecondsF();
340 maxBucketValue
= std::max(histogram
[bucketIndex
], maxBucketValue
);
344 // Draw FPS histogram.
345 paint
.setColor(SkColorSetRGB(130, 130, 130));
346 canvas
->drawLine(histogramBounds
.left() - 1, histogramBounds
.top() - 1, histogramBounds
.left() - 1, histogramBounds
.bottom() + 1, paint
);
347 canvas
->drawLine(histogramBounds
.right() + 1, histogramBounds
.top() - 1, histogramBounds
.right() + 1, histogramBounds
.bottom() + 1, paint
);
349 paint
.setColor(DebugColors::FPSDisplayTextAndGraphColor());
350 const double barHeight
= histogramBounds
.height() / histogramSize
;
352 for (int i
= histogramSize
- 1; i
>= 0; --i
) {
353 if (histogram
[i
] > 0) {
354 double barWidth
= histogram
[i
] / maxBucketValue
* histogramBounds
.width();
355 canvas
->drawRect(SkRect::MakeXYWH(histogramBounds
.left(), histogramBounds
.bottom() - (i
+ 1) * barHeight
, barWidth
, 1), paint
);
360 paint
.setAntiAlias(true);
361 paint
.setStyle(SkPaint::kStroke_Style
);
362 paint
.setStrokeWidth(1);
364 canvas
->drawPath(path
, paint
);
366 return top
+ height
+ 2;
369 int HeadsUpDisplayLayerImpl::drawMemoryDisplay(SkCanvas
* canvas
, MemoryHistory
* memoryHistory
, const int& initial_top
)
371 // Don't draw the display if there is no data in it.
372 if (!memoryHistory
->End())
375 const MemoryHistory::Entry curEntry
= **memoryHistory
->End();
377 // Move up by 2 to create no gap between us and previous counter.
378 const int top
= initial_top
- 2;
379 const int padding
= 4;
380 const int fontHeight
= 11;
382 const int width
= 187;
383 const int height
= 3 * fontHeight
+ 4 * padding
;
385 const int left
= bounds().width() - width
- 2;
386 const double megabyte
= static_cast<double>(1024*1024);
388 SkPaint paint
= createPaint();
389 drawGraphBackground(canvas
, &paint
, SkRect::MakeXYWH(left
, top
, width
, height
));
391 SkPoint titlePos
= SkPoint::Make(left
+ padding
, top
+ fontHeight
);
392 SkPoint stat1Pos
= SkPoint::Make(left
+ width
- padding
- 1, top
+ padding
+ 2 * fontHeight
);
393 SkPoint stat2Pos
= SkPoint::Make(left
+ width
- padding
- 1, top
+ 2 * padding
+ 3 * fontHeight
);
395 paint
.setColor(SkColorSetRGB(220, 220, 220));
396 drawText(canvas
, &paint
, "GPU memory", SkPaint::kLeft_Align
, fontHeight
, titlePos
);
398 std::string text
= base::StringPrintf(
400 (curEntry
.bytes_unreleasable
+ curEntry
.bytes_allocated
) / megabyte
);
401 drawText(canvas
, &paint
, text
, SkPaint::kRight_Align
, fontHeight
, stat1Pos
);
403 if (curEntry
.bytes_over
) {
404 paint
.setColor(SK_ColorRED
);
405 text
= base::StringPrintf("%6.1f MB over",
406 curEntry
.bytes_over
/ megabyte
);
408 text
= base::StringPrintf("%6.1f MB max ",
409 curEntry
.total_budget_in_bytes
/ megabyte
);
411 drawText(canvas
, &paint
, text
, SkPaint::kRight_Align
, fontHeight
, stat2Pos
);
413 return top
+ height
+ 2;
416 int HeadsUpDisplayLayerImpl::drawPaintTimeDisplay(SkCanvas
* canvas
, PaintTimeCounter
* paintTimeCounter
, const int& top
)
418 const int padding
= 4;
419 const int fontHeight
= 15;
421 const int graphWidth
= paintTimeCounter
->HistorySize() * 2 - 1;
422 const int graphHeight
= 40;
424 const int width
= graphWidth
+ 2 * padding
;
425 const int height
= fontHeight
+ graphHeight
+ 4 * padding
+ 2 + fontHeight
+ padding
;
427 const int left
= bounds().width() - width
- 2;
429 SkPaint paint
= createPaint();
430 drawGraphBackground(canvas
, &paint
, SkRect::MakeXYWH(left
, top
, width
, height
));
432 SkRect textBounds
= SkRect::MakeXYWH(left
+ padding
, top
+ padding
, graphWidth
, fontHeight
);
433 SkRect textBounds2
= SkRect::MakeXYWH(left
+ padding
, textBounds
.bottom() + padding
, graphWidth
, fontHeight
);
434 SkRect graphBounds
= SkRect::MakeXYWH(left
+ padding
, textBounds2
.bottom() + 2 * padding
, graphWidth
, graphHeight
);
436 const std::string valueText
= base::StringPrintf("%.1f", m_paintTimeGraph
.value
);
437 const std::string minMaxText
= base::StringPrintf("%.1f-%.1f", m_paintTimeGraph
.min
, m_paintTimeGraph
.max
);
439 paint
.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
440 drawText(canvas
, &paint
, "Page paint time (ms)", SkPaint::kLeft_Align
, fontHeight
, textBounds
.left(), textBounds
.bottom());
441 drawText(canvas
, &paint
, valueText
, SkPaint::kLeft_Align
, fontHeight
, textBounds2
.left(), textBounds2
.bottom());
442 drawText(canvas
, &paint
, minMaxText
, SkPaint::kRight_Align
, fontHeight
, textBounds2
.right(), textBounds2
.bottom());
444 const double upperBound
= Graph::updateUpperBound(&m_paintTimeGraph
);
445 drawGraphLines(canvas
, &paint
, graphBounds
, m_paintTimeGraph
);
447 paint
.setColor(DebugColors::PaintTimeDisplayTextAndGraphColor());
448 for (PaintTimeCounter::RingBufferType::Iterator it
= paintTimeCounter
->End(); it
; --it
) {
449 double pt
= it
->total_time().InMillisecondsF();
454 double p
= pt
/ upperBound
;
458 canvas
->drawRect(SkRect::MakeXYWH(graphBounds
.left() + it
.index() * 2, graphBounds
.bottom() - p
* graphBounds
.height(), 1, p
* graphBounds
.height()), paint
);
461 return top
+ height
+ 2;
464 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas
* canvas
, DebugRectHistory
* debugRectHistory
)
466 const std::vector
<DebugRect
>& debugRects
= debugRectHistory
->debugRects();
467 float rectScale
= 1 / layerTreeImpl()->device_scale_factor();
470 canvas
->scale(rectScale
, rectScale
);
472 for (size_t i
= 0; i
< debugRects
.size(); ++i
) {
473 SkColor strokeColor
= 0;
474 SkColor fillColor
= 0;
475 float strokeWidth
= 0;
477 switch (debugRects
[i
].type
) {
479 strokeColor
= DebugColors::PaintRectBorderColor();
480 fillColor
= DebugColors::PaintRectFillColor();
481 strokeWidth
= DebugColors::PaintRectBorderWidth(layerTreeImpl());
483 case PropertyChangedRectType
:
484 strokeColor
= DebugColors::PropertyChangedRectBorderColor();
485 fillColor
= DebugColors::PropertyChangedRectFillColor();
486 strokeWidth
= DebugColors::PropertyChangedRectBorderWidth(layerTreeImpl());
488 case SurfaceDamageRectType
:
489 strokeColor
= DebugColors::SurfaceDamageRectBorderColor();
490 fillColor
= DebugColors::SurfaceDamageRectFillColor();
491 strokeWidth
= DebugColors::SurfaceDamageRectBorderWidth(layerTreeImpl());
493 case ReplicaScreenSpaceRectType
:
494 strokeColor
= DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor();
495 fillColor
= DebugColors::ScreenSpaceSurfaceReplicaRectFillColor();
496 strokeWidth
= DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth(layerTreeImpl());
498 case ScreenSpaceRectType
:
499 strokeColor
= DebugColors::ScreenSpaceLayerRectBorderColor();
500 fillColor
= DebugColors::ScreenSpaceLayerRectFillColor();
501 strokeWidth
= DebugColors::ScreenSpaceLayerRectBorderWidth(layerTreeImpl());
503 case OccludingRectType
:
504 strokeColor
= DebugColors::OccludingRectBorderColor();
505 fillColor
= DebugColors::OccludingRectFillColor();
506 strokeWidth
= DebugColors::OccludingRectBorderWidth(layerTreeImpl());
508 case NonOccludingRectType
:
509 strokeColor
= DebugColors::NonOccludingRectBorderColor();
510 fillColor
= DebugColors::NonOccludingRectFillColor();
511 strokeWidth
= DebugColors::NonOccludingRectBorderWidth(layerTreeImpl());
515 const gfx::RectF
& rect
= debugRects
[i
].rect
;
516 SkRect skRect
= SkRect::MakeXYWH(rect
.x(), rect
.y(), rect
.width(), rect
.height());
517 SkPaint paint
= createPaint();
518 paint
.setColor(fillColor
);
519 canvas
->drawRect(skRect
, paint
);
521 paint
.setColor(strokeColor
);
522 paint
.setStyle(SkPaint::kStroke_Style
);
523 paint
.setStrokeWidth(SkFloatToScalar(strokeWidth
));
524 canvas
->drawRect(skRect
, paint
);
530 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const
532 return "HeadsUpDisplayLayer";