• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 #include "config.h"
26 
27 #if USE(ACCELERATED_COMPOSITING)
28 #include "CCHeadsUpDisplay.h"
29 
30 #include "CurrentTime.h"
31 #include "Font.h"
32 #include "FontDescription.h"
33 #include "GraphicsContext3D.h"
34 #include "LayerChromium.h"
35 #include "LayerRendererChromium.h"
36 #include "LayerTexture.h"
37 #include "TextRun.h"
38 #include "TextStream.h"
39 #include "TextureManager.h"
40 #include <wtf/text/CString.h>
41 #include <wtf/text/WTFString.h>
42 
43 namespace WebCore {
44 
45 using namespace std;
46 
CCHeadsUpDisplay(LayerRendererChromium * owner)47 CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner)
48     : m_currentFrameNumber(1)
49     , m_filteredFrameTime(0)
50     , m_layerRenderer(owner)
51     , m_showFPSCounter(false)
52     , m_showPlatformLayerTree(false)
53 {
54     m_presentTimeHistoryInSec[0] = currentTime();
55     m_presentTimeHistoryInSec[1] = m_presentTimeHistoryInSec[0];
56     for (int i = 2; i < kPresentHistorySize; i++)
57         m_presentTimeHistoryInSec[i] = 0;
58 
59     FontDescription mediumFontDesc;
60     mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
61     mediumFontDesc.setComputedSize(20);
62 
63     m_mediumFont = adoptPtr(new Font(mediumFontDesc, 0, 0));
64     m_mediumFont->update(0);
65 
66     FontDescription smallFontDesc;
67     smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily);
68     smallFontDesc.setComputedSize(10);
69 
70     m_smallFont = adoptPtr(new Font(smallFontDesc, 0, 0));
71     m_smallFont->update(0);
72 }
73 
~CCHeadsUpDisplay()74 CCHeadsUpDisplay::~CCHeadsUpDisplay()
75 {
76 }
77 
draw()78 void CCHeadsUpDisplay::draw()
79 {
80     GraphicsContext3D* context = m_layerRenderer->context();
81     if (!m_hudTexture)
82         m_hudTexture = LayerTexture::create(context, m_layerRenderer->textureManager());
83 
84     // Use a fullscreen texture only if we need to...
85     IntSize hudSize;
86     if (m_showPlatformLayerTree) {
87         hudSize.setWidth(min(2048, m_layerRenderer->viewportSize().width()));
88         hudSize.setHeight(min(2048, m_layerRenderer->viewportSize().height()));
89     } else {
90         hudSize.setWidth(512);
91         hudSize.setHeight(128);
92     }
93 
94     m_hudTexture->reserve(hudSize, GraphicsContext3D::RGBA);
95 
96     // Render pixels into the texture.
97     PlatformCanvas canvas;
98     canvas.resize(hudSize);
99     {
100         PlatformCanvas::Painter painter(&canvas, PlatformCanvas::Painter::GrayscaleText);
101         drawHudContents(painter.context(), hudSize);
102     }
103 
104     // Upload to GL.
105     {
106         PlatformCanvas::AutoLocker locker(&canvas);
107 
108         m_hudTexture->bindTexture();
109         GLC(context.get(), context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, canvas.size().width(), canvas.size().height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, locker.pixels()));
110     }
111 
112     // Draw the HUD onto the default render surface.
113     const Program* program = m_layerRenderer->headsUpDisplayProgram();
114     ASSERT(program && program->initialized());
115     GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
116     m_hudTexture->bindTexture();
117     m_layerRenderer->useShader(program->program());
118     GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
119 
120     TransformationMatrix matrix;
121     matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
122     LayerChromium::drawTexturedQuad(context, m_layerRenderer->projectionMatrix(),
123                                     matrix, hudSize.width(), hudSize.height(),
124                                     1.0f, program->vertexShader().matrixLocation(),
125                                     program->fragmentShader().alphaLocation());
126 }
127 
drawHudContents(GraphicsContext * ctx,const IntSize & hudSize)128 void CCHeadsUpDisplay::drawHudContents(GraphicsContext* ctx, const IntSize& hudSize)
129 {
130     if (m_showPlatformLayerTree) {
131         ctx->setFillColor(Color(0, 0, 0, 192), ColorSpaceDeviceRGB);
132         ctx->fillRect(FloatRect(0, 0, hudSize.width(), hudSize.height()));
133     }
134 
135     int fpsCounterHeight = m_mediumFont->fontMetrics().floatHeight() + 2;
136     int fpsCounterTop = 2;
137     int platformLayerTreeTop;
138     if (m_showFPSCounter)
139         platformLayerTreeTop = fpsCounterTop + fpsCounterHeight + 2;
140     else
141         platformLayerTreeTop = 0;
142 
143     if (m_showFPSCounter)
144         drawFPSCounter(ctx, fpsCounterTop, fpsCounterHeight);
145 
146     if (m_showPlatformLayerTree)
147         drawPlatformLayerTree(ctx, platformLayerTreeTop);
148 }
149 
drawFPSCounter(GraphicsContext * ctx,int top,int height)150 void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* ctx, int top, int height)
151 {
152     // Note that since we haven't finished the current frame, the FPS counter
153     // actually reports the last frame's time.
154     double secForLastFrame = m_presentTimeHistoryInSec[(m_currentFrameNumber + kPresentHistorySize - 1) % kPresentHistorySize] -
155                              m_presentTimeHistoryInSec[(m_currentFrameNumber + kPresentHistorySize - 2) % kPresentHistorySize];
156 
157     // Filter the frame times to avoid spikes.
158     const float alpha = 0.1;
159     if (!m_filteredFrameTime) {
160         if (m_currentFrameNumber == 2)
161             m_filteredFrameTime = secForLastFrame;
162     } else
163         m_filteredFrameTime = ((1.0 - alpha) * m_filteredFrameTime) + (alpha * secForLastFrame);
164 
165     // Create & measure FPS text.
166     String text(String::format("FPS: %5.1f", 1.0 / m_filteredFrameTime));
167     TextRun run(text);
168     float textWidth = m_mediumFont->width(run) + 2.0f;
169     float graphWidth = kPresentHistorySize;
170 
171     // Draw background.
172     ctx->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB);
173     ctx->fillRect(FloatRect(2, top, textWidth + graphWidth, height));
174 
175     // Draw FPS text.
176     if (m_filteredFrameTime) {
177         ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
178         ctx->drawText(*m_mediumFont, run, IntPoint(3, top + height - 6));
179     }
180 
181     // Draw FPS graph.
182     const double loFPS = 0.0;
183     const double hiFPS = 120.0;
184     ctx->setStrokeStyle(SolidStroke);
185     ctx->setStrokeColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
186     int graphLeft = static_cast<int>(textWidth + 3);
187     IntPoint prev(-1, 0);
188     int x = 0;
189     double h = static_cast<double>(height - 2);
190     for (int i = m_currentFrameNumber % kPresentHistorySize; i != (m_currentFrameNumber - 1) % kPresentHistorySize; i = (i + 1) % kPresentHistorySize) {
191         int j = (i + 1) % kPresentHistorySize;
192         double fps = 1.0 / (m_presentTimeHistoryInSec[j] - m_presentTimeHistoryInSec[i]);
193         double p = 1 - ((fps - loFPS) / (hiFPS - loFPS));
194         if (p < 0)
195             p = 0;
196         if (p > 1)
197             p = 1;
198         IntPoint cur(graphLeft + x, 1 + top + p*h);
199         if (prev.x() != -1)
200             ctx->drawLine(prev, cur);
201         prev = cur;
202         x += 1;
203     }
204 }
205 
drawPlatformLayerTree(GraphicsContext * ctx,int top)206 void CCHeadsUpDisplay::drawPlatformLayerTree(GraphicsContext* ctx, int top)
207 {
208     float smallFontHeight = m_smallFont->fontMetrics().floatHeight();
209     int y = top + smallFontHeight - 4;
210     ctx->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB);
211     Vector<String> lines;
212     m_layerRenderer->layerTreeAsText().split('\n', lines);
213     for (size_t i = 0; i < lines.size(); ++i) {
214         ctx->drawText(*m_smallFont, TextRun(lines[i]), IntPoint(2, y));
215         y += smallFontHeight;
216     }
217 }
218 
onPresent()219 void CCHeadsUpDisplay::onPresent()
220 {
221     m_presentTimeHistoryInSec[m_currentFrameNumber % kPresentHistorySize] = currentTime();
222     m_currentFrameNumber += 1;
223 }
224 
225 }
226 
227 #endif // USE(ACCELERATED_COMPOSITING)
228