[chromium] Replace destRect with destOffset in texture upload
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCHeadsUpDisplayLayerImpl.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "cc/CCHeadsUpDisplayLayerImpl.h"
29
30 #include "Extensions3DChromium.h"
31 #include "GraphicsContext3D.h"
32 #include "LayerRendererChromium.h"
33 #include "SkBitmap.h"
34 #include "SkColorMatrixFilter.h"
35 #include "SkPaint.h"
36 #include "cc/CCDebugRectHistory.h"
37 #include "cc/CCFontAtlas.h"
38 #include "cc/CCFrameRateCounter.h"
39 #include "cc/CCLayerTreeHostImpl.h"
40 #include "cc/CCQuadSink.h"
41 #include "cc/CCTextureDrawQuad.h"
42 #include "skia/ext/platform_canvas.h"
43 #include <wtf/text/WTFString.h>
44
45 namespace WebCore {
46
47 static inline SkPaint createPaint()
48 {
49     // The SkCanvas is in RGBA but the shader is expecting BGRA, so we need to
50     // swizzle our colors when drawing to the SkCanvas.
51     SkColorMatrix swizzleMatrix;
52     for (int i = 0; i < 20; ++i)
53         swizzleMatrix.fMat[i] = 0;
54     swizzleMatrix.fMat[0 + 5 * 2] = 1;
55     swizzleMatrix.fMat[1 + 5 * 1] = 1;
56     swizzleMatrix.fMat[2 + 5 * 0] = 1;
57     swizzleMatrix.fMat[3 + 5 * 3] = 1;
58
59     SkPaint paint;
60     paint.setColorFilter(new SkColorMatrixFilter(swizzleMatrix))->unref();
61     return paint;
62 }
63
64 CCHeadsUpDisplayLayerImpl::CCHeadsUpDisplayLayerImpl(int id)
65     : CCLayerImpl(id)
66 {
67 }
68
69 CCHeadsUpDisplayLayerImpl::~CCHeadsUpDisplayLayerImpl()
70 {
71 }
72
73 void CCHeadsUpDisplayLayerImpl::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
74 {
75     m_fontAtlas = fontAtlas;
76 }
77
78 void CCHeadsUpDisplayLayerImpl::willDraw(CCResourceProvider* resourceProvider)
79 {
80     CCLayerImpl::willDraw(resourceProvider);
81
82     if (!m_hudTexture)
83         m_hudTexture = CCScopedTexture::create(resourceProvider);
84
85     // FIXME: Scale the HUD by deviceScale to make it more friendly under high DPI.
86
87     if (m_hudTexture->size() != bounds())
88         m_hudTexture->free();
89
90     if (!m_hudTexture->id() && !m_hudTexture->allocate(CCRenderer::ImplPool, bounds(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageAny))
91         return;
92
93     SkISize canvasSize;
94     if (m_hudCanvas)
95         canvasSize = m_hudCanvas->getDeviceSize();
96     else
97         canvasSize.set(0, 0);
98
99     if (canvasSize.fWidth != bounds().width() || canvasSize.fHeight != bounds().height() || !m_hudCanvas)
100         m_hudCanvas = adoptPtr(skia::CreateBitmapCanvas(bounds().width(), bounds().height(), false /* opaque */));
101
102     m_hudCanvas->clear(SkColorSetARGB(0, 0, 0, 0));
103     drawHudContents(m_hudCanvas.get());
104
105     const SkBitmap* bitmap = &m_hudCanvas->getDevice()->accessBitmap(false);
106     SkAutoLockPixels locker(*bitmap);
107
108     IntRect layerRect(IntPoint(), bounds());
109     ASSERT(bitmap->config() == SkBitmap::kARGB_8888_Config);
110     resourceProvider->upload(m_hudTexture->id(), static_cast<const uint8_t*>(bitmap->getPixels()), layerRect, layerRect, IntSize());
111 }
112
113 void CCHeadsUpDisplayLayerImpl::appendQuads(CCQuadSink& quadList, const CCSharedQuadState* sharedQuadState, bool&)
114 {
115     if (!m_hudTexture->id())
116         return;
117
118     IntRect quadRect(IntPoint(), bounds());
119     bool premultipliedAlpha = true;
120     FloatRect uvRect(0, 0, 1, 1);
121     bool flipped = false;
122     quadList.append(CCTextureDrawQuad::create(sharedQuadState, quadRect, m_hudTexture->id(), premultipliedAlpha, uvRect, flipped));
123 }
124
125 void CCHeadsUpDisplayLayerImpl::didDraw(CCResourceProvider* resourceProvider)
126 {
127     CCLayerImpl::didDraw(resourceProvider);
128
129     if (!m_hudTexture->id())
130         return;
131
132     // FIXME: the following assert will not be true when sending resources to a
133     // parent compositor. We will probably need to hold on to m_hudTexture for
134     // longer, and have several HUD textures in the pipeline.
135     ASSERT(!resourceProvider->inUseByConsumer(m_hudTexture->id()));
136 }
137
138 void CCHeadsUpDisplayLayerImpl::didLoseContext()
139 {
140     m_hudTexture.clear();
141 }
142
143 void CCHeadsUpDisplayLayerImpl::drawHudContents(SkCanvas* canvas)
144 {
145     const CCLayerTreeSettings& settings = layerTreeHostImpl()->settings();
146
147     if (settings.showPlatformLayerTree) {
148         SkPaint paint = createPaint();
149         paint.setColor(SkColorSetARGB(192, 0, 0, 0));
150         canvas->drawRect(SkRect::MakeXYWH(0, 0, bounds().width(), bounds().height()), paint);
151     }
152
153     int fpsCounterHeight = 40;
154     int fpsCounterTop = 2;
155     int platformLayerTreeTop;
156
157     if (settings.showFPSCounter)
158         platformLayerTreeTop = fpsCounterTop + fpsCounterHeight;
159     else
160         platformLayerTreeTop = 0;
161
162     if (settings.showFPSCounter)
163         drawFPSCounter(canvas, layerTreeHostImpl()->fpsCounter(), fpsCounterTop, fpsCounterHeight);
164
165     if (settings.showPlatformLayerTree && m_fontAtlas) {
166         String layerTree = layerTreeHostImpl()->layerTreeAsText();
167         m_fontAtlas->drawText(canvas, createPaint(), layerTree, IntPoint(2, platformLayerTreeTop), bounds());
168     }
169
170     if (settings.showDebugRects())
171         drawDebugRects(canvas, layerTreeHostImpl()->debugRectHistory());
172 }
173
174 void CCHeadsUpDisplayLayerImpl::drawFPSCounter(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int height)
175 {
176     float textWidth = 170; // so text fits on linux.
177     float graphWidth = fpsCounter->timeStampHistorySize();
178
179     // Draw the FPS text.
180     drawFPSCounterText(canvas, fpsCounter, top, textWidth, height);
181
182     // Draw FPS graph.
183     const double loFPS = 0;
184     const double hiFPS = 80;
185     SkPaint paint = createPaint();
186     paint.setColor(SkColorSetRGB(154, 205, 50));
187     canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top, graphWidth, height / 2), paint);
188
189     paint.setColor(SkColorSetRGB(255, 250, 205));
190     canvas->drawRect(SkRect::MakeXYWH(2 + textWidth, top + height / 2, graphWidth, height / 2), paint);
191
192     int graphLeft = static_cast<int>(textWidth + 3);
193     int x = 0;
194     double h = static_cast<double>(height - 2);
195     SkPath path;
196     for (int i = 0; i < fpsCounter->timeStampHistorySize() - 1; ++i) {
197         int j = i + 1;
198         double delta = fpsCounter->timeStampOfRecentFrame(j) - fpsCounter->timeStampOfRecentFrame(i);
199
200         // Skip plotting this particular instantaneous frame rate if it is not likely to have been valid.
201         if (fpsCounter->isBadFrameInterval(delta)) {
202             x += 1;
203             continue;
204         }
205
206         double fps = 1.0 / delta;
207
208         // Clamp the FPS to the range we want to plot visually.
209         double p = 1 - ((fps - loFPS) / (hiFPS - loFPS));
210         if (p < 0)
211             p = 0;
212         if (p > 1)
213             p = 1;
214
215         // Plot this data point.
216         SkPoint cur = SkPoint::Make(graphLeft + x, 1 + top + p*h);
217         if (path.isEmpty())
218             path.moveTo(cur);
219         else
220             path.lineTo(cur);
221         x += 1;
222     }
223     paint.setColor(SK_ColorRED);
224     paint.setStyle(SkPaint::kStroke_Style);
225     paint.setStrokeWidth(1);
226     paint.setAntiAlias(true);
227     canvas->drawPath(path, paint);
228 }
229
230 void CCHeadsUpDisplayLayerImpl::drawFPSCounterText(SkCanvas* canvas, CCFrameRateCounter* fpsCounter, int top, int width, int height)
231 {
232     double averageFPS, stdDeviation;
233     fpsCounter->getAverageFPSAndStandardDeviation(averageFPS, stdDeviation);
234
235     // Draw background.
236     SkPaint paint = createPaint();
237     paint.setColor(SK_ColorBLACK);
238     canvas->drawRect(SkRect::MakeXYWH(2, top, width, height), paint);
239
240     // Draw FPS text.
241     if (m_fontAtlas)
242         m_fontAtlas->drawText(canvas, createPaint(), String::format("FPS: %4.1f +/- %3.1f", averageFPS, stdDeviation), IntPoint(10, height / 3), IntSize(width, height));
243 }
244
245 void CCHeadsUpDisplayLayerImpl::drawDebugRects(SkCanvas* canvas, CCDebugRectHistory* debugRectHistory)
246 {
247     const Vector<CCDebugRect>& debugRects = debugRectHistory->debugRects();
248
249     for (size_t i = 0; i < debugRects.size(); ++i) {
250         SkColor strokeColor = 0;
251         SkColor fillColor = 0;
252
253         switch (debugRects[i].type) {
254         case PaintRectType:
255             // Paint rects in red
256             strokeColor = SkColorSetARGB(255, 255, 0, 0);
257             fillColor = SkColorSetARGB(30, 255, 0, 0);
258             break;
259         case PropertyChangedRectType:
260             // Property-changed rects in blue
261             strokeColor = SkColorSetARGB(255, 255, 0, 0);
262             fillColor = SkColorSetARGB(30, 0, 0, 255);
263             break;
264         case SurfaceDamageRectType:
265             // Surface damage rects in yellow-orange
266             strokeColor = SkColorSetARGB(255, 200, 100, 0);
267             fillColor = SkColorSetARGB(30, 200, 100, 0);
268             break;
269         case ReplicaScreenSpaceRectType:
270             // Screen space rects in green.
271             strokeColor = SkColorSetARGB(255, 100, 200, 0);
272             fillColor = SkColorSetARGB(30, 100, 200, 0);
273             break;
274         case ScreenSpaceRectType:
275             // Screen space rects in purple.
276             strokeColor = SkColorSetARGB(255, 100, 0, 200);
277             fillColor = SkColorSetARGB(10, 100, 0, 200);
278             break;
279         case OccludingRectType:
280             // Occluding rects in a reddish color.
281             strokeColor = SkColorSetARGB(255, 200, 0, 100);
282             fillColor = SkColorSetARGB(10, 200, 0, 100);
283             break;
284         }
285
286         const FloatRect& rect = debugRects[i].rect;
287         SkRect skRect = SkRect::MakeXYWH(rect.x(), rect.y(), rect.width(), rect.height());
288         SkPaint paint = createPaint();
289         paint.setColor(fillColor);
290         canvas->drawRect(skRect, paint);
291
292         paint.setColor(strokeColor);
293         paint.setStyle(SkPaint::kStroke_Style);
294         paint.setStrokeWidth(2);
295         canvas->drawRect(skRect, paint);
296     }
297 }
298
299 }