Use SCHEME_HTTP for HTTPS proxies on Android.
[chromium-blink-merge.git] / cc / heads_up_display_layer_impl.cc
blob4490519b793cb1878c8f0cc2e0b61845c491dfc7
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 <limits>
9 #include "base/stringprintf.h"
10 #include "cc/debug_colors.h"
11 #include "cc/debug_rect_history.h"
12 #include "cc/font_atlas.h"
13 #include "cc/frame_rate_counter.h"
14 #include "cc/layer_tree_host_impl.h"
15 #include "cc/quad_sink.h"
16 #include "cc/texture_draw_quad.h"
17 #include "skia/ext/platform_canvas.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "third_party/khronos/GLES2/gl2.h"
20 #include "third_party/khronos/GLES2/gl2ext.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "third_party/skia/include/core/SkPaint.h"
23 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
24 #include "ui/gfx/point.h"
25 #include "ui/gfx/size.h"
27 namespace cc {
29 static inline SkPaint createPaint()
31 // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to
32 // swizzle our colors when drawing to the SkCanvas.
33 SkColorMatrix swizzleMatrix;
34 for (int i = 0; i < 20; ++i)
35 swizzleMatrix.fMat[i] = 0;
36 swizzleMatrix.fMat[0 + 5 * 2] = 1;
37 swizzleMatrix.fMat[1 + 5 * 1] = 1;
38 swizzleMatrix.fMat[2 + 5 * 0] = 1;
39 swizzleMatrix.fMat[3 + 5 * 3] = 1;
41 SkPaint paint;
42 skia::RefPtr<SkColorMatrixFilter> filter =
43 skia::AdoptRef(new SkColorMatrixFilter(swizzleMatrix));
44 paint.setColorFilter(filter.get());
46 return paint;
49 HeadsUpDisplayLayerImpl::HeadsUpDisplayLayerImpl(LayerTreeHostImpl* hostImpl, int id)
50 : LayerImpl(hostImpl, id)
51 , m_averageFPS(0)
52 , m_minFPS(0)
53 , m_maxFPS(0)
57 HeadsUpDisplayLayerImpl::~HeadsUpDisplayLayerImpl()
61 void HeadsUpDisplayLayerImpl::setFontAtlas(scoped_ptr<FontAtlas> fontAtlas)
63 m_fontAtlas = fontAtlas.Pass();
66 void HeadsUpDisplayLayerImpl::willDraw(ResourceProvider* resourceProvider)
68 LayerImpl::willDraw(resourceProvider);
70 if (!m_hudTexture)
71 m_hudTexture = ScopedResource::create(resourceProvider);
73 // FIXME: Scale the HUD by deviceScale to make it more friendly under high DPI.
75 if (m_hudTexture->size() != bounds())
76 m_hudTexture->Free();
78 if (!m_hudTexture->id())
79 m_hudTexture->Allocate(Renderer::ImplPool, bounds(), GL_RGBA, ResourceProvider::TextureUsageAny);
82 void HeadsUpDisplayLayerImpl::appendQuads(QuadSink& quadSink, AppendQuadsData& appendQuadsData)
84 if (!m_hudTexture->id())
85 return;
87 SharedQuadState* sharedQuadState = quadSink.useSharedQuadState(createSharedQuadState());
89 gfx::Rect quadRect(gfx::Point(), bounds());
90 gfx::Rect opaqueRect(contentsOpaque() ? quadRect : gfx::Rect());
91 bool premultipliedAlpha = true;
92 gfx::RectF uvRect(0, 0, 1, 1);
93 bool flipped = false;
94 scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
95 quad->SetNew(sharedQuadState, quadRect, opaqueRect, m_hudTexture->id(), premultipliedAlpha, uvRect, flipped);
96 quadSink.append(quad.PassAs<DrawQuad>(), appendQuadsData);
99 void HeadsUpDisplayLayerImpl::updateHudTexture(ResourceProvider* resourceProvider)
101 if (!m_hudTexture->id())
102 return;
104 SkISize canvasSize;
105 if (m_hudCanvas)
106 canvasSize = m_hudCanvas->getDeviceSize();
107 else
108 canvasSize.set(0, 0);
110 if (canvasSize.fWidth != bounds().width() || canvasSize.fHeight != bounds().height() || !m_hudCanvas)
111 m_hudCanvas = make_scoped_ptr(skia::CreateBitmapCanvas(bounds().width(), bounds().height(), false /* opaque */));
113 m_hudCanvas->clear(SkColorSetARGB(0, 0, 0, 0));
114 drawHudContents(m_hudCanvas.get());
116 const SkBitmap* bitmap = &m_hudCanvas->getDevice()->accessBitmap(false);
117 SkAutoLockPixels locker(*bitmap);
119 gfx::Rect layerRect(gfx::Point(), bounds());
120 DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
121 resourceProvider->setPixels(m_hudTexture->id(), static_cast<const uint8_t*>(bitmap->getPixels()), layerRect, layerRect, gfx::Vector2d());
124 void HeadsUpDisplayLayerImpl::didDraw(ResourceProvider* resourceProvider)
126 LayerImpl::didDraw(resourceProvider);
128 if (!m_hudTexture->id())
129 return;
131 // FIXME: the following assert will not be true when sending resources to a
132 // parent compositor. We will probably need to hold on to m_hudTexture for
133 // longer, and have several HUD textures in the pipeline.
134 DCHECK(!resourceProvider->inUseByConsumer(m_hudTexture->id()));
137 void HeadsUpDisplayLayerImpl::didLoseOutputSurface()
139 m_hudTexture.reset();
142 bool HeadsUpDisplayLayerImpl::layerIsAlwaysDamaged() const
144 return true;
147 void HeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas)
149 const LayerTreeDebugState& debugState = layerTreeHostImpl()->debugState();
151 if (debugState.showPlatformLayerTree) {
152 SkPaint paint = createPaint();
153 paint.setColor(SkColorSetARGB(192, 0, 0, 0));
154 canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()), paint);
157 int platformLayerTreeTop = 0;
159 if (debugState.showFPSCounter)
160 platformLayerTreeTop = drawFPSCounter(canvas, layerTreeHostImpl()->fpsCounter());
162 if (debugState.showPlatformLayerTree && m_fontAtlas) {
163 std::string layerTree = layerTreeHostImpl()->layerTreeAsText();
164 m_fontAtlas->drawText(canvas, createPaint(), layerTree, gfx::Point(2, platformLayerTreeTop), bounds());
167 if (debugState.showHudRects())
168 drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory());
171 int HeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, FrameRateCounter* fpsCounter)
173 const int padding = 4;
174 const int gap = 6;
176 const int fontHeight = m_fontAtlas.get() ? m_fontAtlas->fontHeight() : 0;
178 const int graphWidth = 120;
179 const int graphHeight = 40;
181 const int histogramWidth = 37;
183 const int width = graphWidth + histogramWidth + 4 * padding;
184 const int height = fontHeight + graphHeight + 4 * padding + 2;
186 const int left = bounds().width() - width - 2;
187 const int top = 2;
189 SkPaint paint = createPaint();
191 // Draw background.
192 paint.setColor(SkColorSetARGB(215, 17, 17, 17));
193 canvas->drawRect(SkRect::MakeXYWH(left, top, width, height), paint);
195 SkRect textBounds = SkRect::MakeXYWH(left + padding, top + padding, graphWidth + histogramWidth + gap + 2, fontHeight);
196 SkRect graphBounds = SkRect::MakeXYWH(left + padding, textBounds.bottom() + 2 * padding, graphWidth, graphHeight);
197 SkRect histogramBounds = SkRect::MakeXYWH(graphBounds.right() + gap, graphBounds.top(), histogramWidth, graphHeight);
199 drawFPSCounterText(canvas, paint, fpsCounter, textBounds);
200 drawFPSCounterGraphAndHistogram(canvas, paint, fpsCounter, graphBounds, histogramBounds);
202 return top + height;
205 void HeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, SkPaint& paint, FrameRateCounter* fpsCounter, SkRect bounds)
207 // Update FPS text - not every frame so text is readable
208 if (base::TimeDelta(fpsCounter->timeStampOfRecentFrame(0) - textUpdateTime).InSecondsF() > 0.25) {
209 m_averageFPS = fpsCounter->getAverageFPS();
210 textUpdateTime = fpsCounter->timeStampOfRecentFrame(0);
213 // Draw FPS text.
214 if (m_fontAtlas.get()) {
215 std::string fpsText = base::StringPrintf("FPS:%5.1f", m_averageFPS);
216 std::string minMaxText = base::StringPrintf("%.0f-%.0f", std::min( m_minFPS, m_maxFPS), m_maxFPS);
218 int minMaxWidth = m_fontAtlas->textSize(minMaxText).width();
219 gfx::Size textArea(bounds.width(), bounds.height());
221 paint.setColor(SK_ColorRED);
222 m_fontAtlas->drawText(canvas, paint, fpsText, gfx::Point(bounds.left(), bounds.top()), textArea);
223 m_fontAtlas->drawText(canvas, paint, minMaxText, gfx::Point(bounds.right() - minMaxWidth, bounds.top()), textArea);
227 void HeadsUpDisplayLayerImpl::drawFPSCounterGraphAndHistogram(SkCanvas* canvas, SkPaint& paint, FrameRateCounter* fpsCounter, SkRect graphBounds, SkRect histogramBounds)
229 const double loFPS = 0;
230 const double hiFPS = std::max(m_maxFPS + 10.0, 80.0);
232 // Draw top and bottom line.
233 paint.setColor(SkColorSetRGB(130, 130, 130));
234 canvas->drawLine(graphBounds.left(), graphBounds.top() - 1, graphBounds.right(), graphBounds.top() - 1, paint);
235 canvas->drawLine(graphBounds.left(), graphBounds.bottom(), graphBounds.right(), graphBounds.bottom(), paint);
237 // Draw 60fps line.
238 const double top60 = graphBounds.top() + graphBounds.height() * (1 - ((60 - loFPS) / (hiFPS - loFPS))) - 1;
239 paint.setColor(SkColorSetRGB(100, 100, 100));
240 canvas->drawLine(graphBounds.left(), top60, graphBounds.right(), top60, paint);
242 // Collect graph and histogram data.
243 double x = 0;
244 const double timeScale = 60; // in pixels/second
245 SkPath path;
247 m_minFPS = std::numeric_limits<double>::max();
248 m_maxFPS = 0;
250 const int histogramSize = 20;
251 double histogram[histogramSize] = {0};
252 double maxBucketValue = 0;
254 for (int i = fpsCounter->timeStampHistorySize() - 2; i > 0 && x <= graphBounds.width(); --i) {
255 base::TimeDelta delta = fpsCounter->timeStampOfRecentFrame(i + 1) - fpsCounter->timeStampOfRecentFrame(i);
257 // Skip this particular instantaneous frame rate if it is not likely to have been valid.
258 if (!fpsCounter->isBadFrameInterval(delta)) {
260 double fps = 1.0 / delta.InSecondsF();
262 m_minFPS = std::min(fps, m_minFPS);
263 m_maxFPS = std::max(fps, m_maxFPS);
265 // Clamp the FPS to the range we want to plot visually.
266 double p = (fps - loFPS) / (hiFPS - loFPS);
267 if (p < 0)
268 p = 0;
269 if (p > 1)
270 p = 1;
272 // Plot this data point.
273 SkPoint cur = SkPoint::Make(graphBounds.right() - x, graphBounds.bottom() - p * graphBounds.height());
274 if (path.isEmpty())
275 path.moveTo(cur);
276 else
277 path.lineTo(cur);
279 // Use the fps value to find the right bucket in the histogram.
280 int bucketIndex = floor(p * (histogramSize - 1));
282 // Add the delta time to take the time spent at that fps rate into account.
283 histogram[bucketIndex] += delta.InSecondsF();
284 maxBucketValue = std::max(histogram[bucketIndex], maxBucketValue);
287 x += delta.InSecondsF() * timeScale;
290 // Draw FPS histogram.
291 paint.setColor(SkColorSetRGB(130, 130, 130));
292 canvas->drawLine(histogramBounds.left() - 1, histogramBounds.top() - 1, histogramBounds.left() - 1, histogramBounds.bottom() + 1, paint);
293 canvas->drawLine(histogramBounds.right() + 1, histogramBounds.top() - 1, histogramBounds.right() + 1, histogramBounds.bottom() + 1, paint);
295 paint.setColor(SK_ColorRED);
296 const double barHeight = histogramBounds.height() / histogramSize;
298 for (int i = histogramSize - 1; i >= 0; --i) {
299 if (histogram[i] > 0) {
300 double barWidth = histogram[i] / maxBucketValue * histogramBounds.width();
301 canvas->drawRect(SkRect::MakeXYWH(histogramBounds.left(), histogramBounds.bottom() - (i + 1) * barHeight, barWidth, 1), paint);
305 // Draw FPS graph.
306 paint.setAntiAlias(true);
307 paint.setStyle(SkPaint::kStroke_Style);
308 paint.setStrokeWidth(1);
310 canvas->drawPath(path, paint);
313 void HeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, DebugRectHistory* debugRectHistory)
315 const std::vector<DebugRect>& debugRects = debugRectHistory->debugRects();
316 float rectScale = 1 / layerTreeHostImpl()->deviceScaleFactor();
318 canvas->save();
319 canvas->scale(rectScale, rectScale);
321 for (size_t i = 0; i < debugRects.size(); ++i) {
322 SkColor strokeColor = 0;
323 SkColor fillColor = 0;
324 float strokeWidth = 0;
326 switch (debugRects[i].type) {
327 case PaintRectType:
328 strokeColor = DebugColors::PaintRectBorderColor();
329 fillColor = DebugColors::PaintRectFillColor();
330 strokeWidth = DebugColors::PaintRectBorderWidth(layerTreeHostImpl());
331 break;
332 case PropertyChangedRectType:
333 strokeColor = DebugColors::PropertyChangedRectBorderColor();
334 fillColor = DebugColors::PropertyChangedRectFillColor();
335 strokeWidth = DebugColors::PropertyChangedRectBorderWidth(layerTreeHostImpl());
336 break;
337 case SurfaceDamageRectType:
338 strokeColor = DebugColors::SurfaceDamageRectBorderColor();
339 fillColor = DebugColors::SurfaceDamageRectFillColor();
340 strokeWidth = DebugColors::SurfaceDamageRectBorderWidth(layerTreeHostImpl());
341 break;
342 case ReplicaScreenSpaceRectType:
343 strokeColor = DebugColors::ScreenSpaceSurfaceReplicaRectBorderColor();
344 fillColor = DebugColors::ScreenSpaceSurfaceReplicaRectFillColor();
345 strokeWidth = DebugColors::ScreenSpaceSurfaceReplicaRectBorderWidth(layerTreeHostImpl());
346 break;
347 case ScreenSpaceRectType:
348 strokeColor = DebugColors::ScreenSpaceLayerRectBorderColor();
349 fillColor = DebugColors::ScreenSpaceLayerRectFillColor();
350 strokeWidth = DebugColors::ScreenSpaceLayerRectBorderWidth(layerTreeHostImpl());
351 break;
352 case OccludingRectType:
353 strokeColor = DebugColors::OccludingRectBorderColor();
354 fillColor = DebugColors::OccludingRectFillColor();
355 strokeWidth = DebugColors::OccludingRectBorderWidth(layerTreeHostImpl());
356 break;
357 case NonOccludingRectType:
358 strokeColor = DebugColors::NonOccludingRectBorderColor();
359 fillColor = DebugColors::NonOccludingRectFillColor();
360 strokeWidth = DebugColors::NonOccludingRectBorderWidth(layerTreeHostImpl());
361 break;
364 const gfx::RectF& rect = debugRects[i].rect;
365 SkRect skRect = SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
366 SkPaint paint = createPaint();
367 paint.setColor(fillColor);
368 canvas->drawRect(skRect, paint);
370 paint.setColor(strokeColor);
371 paint.setStyle(SkPaint::kStroke_Style);
372 paint.setStrokeWidth(SkFloatToScalar(strokeWidth));
373 canvas->drawRect(skRect, paint);
376 canvas->restore();
379 const char* HeadsUpDisplayLayerImpl::layerTypeAsString() const
381 return "HeadsUpDisplayLayer";
384 } // namespace cc