From e58b81e123305d274130e22e4730e5205ca81e68 Mon Sep 17 00:00:00 2001 From: "shawnsingh@chromium.org" Date: Fri, 13 Apr 2012 18:06:50 +0000 Subject: [PATCH] [chromium] Support CCHeadsUpDisplay in threaded compositing mode https://bugs.webkit.org/show_bug.cgi?id=67499 Reviewed by James Robinson. No new tests because this code is debugging code itself. The last item that was needed to make the CCHeadsUpDisplay work in threaded compositing mode was to remove the font rendering code used on the impl-side thread. To solve this, this patch adds a CCFontAtlas that is initialized on the main thread (where the font rendering takes place). Then, when the HUD draws text on the impl thread, it uses the font atlas directly. * WebCore.gypi: * platform/graphics/chromium/LayerRendererChromium.cpp: (WebCore::LayerRendererChromium::create): (WebCore::LayerRendererChromium::initialize): * platform/graphics/chromium/LayerRendererChromium.h: (WebCore): (LayerRendererChromium): * platform/graphics/chromium/cc/CCFontAtlas.cpp: Added. (WebCore): (WebCore::CCFontAtlas::CCFontAtlas): (WebCore::wrapPositionIfNeeded): (WebCore::CCFontAtlas::generateAtlasForFont): (WebCore::CCFontAtlas::initialize): (WebCore::CCFontAtlas::drawText): (WebCore::CCFontAtlas::drawOneLineOfTextInternal): (WebCore::CCFontAtlas::drawDebugAtlas): * platform/graphics/chromium/cc/CCFontAtlas.h: Added. (WebCore): (CCFontAtlas): (WebCore::CCFontAtlas::create): * platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp: (WebCore::CCHeadsUpDisplay::CCHeadsUpDisplay): (WebCore): (WebCore::CCHeadsUpDisplay::showPlatformLayerTree): (WebCore::CCHeadsUpDisplay::drawHudContents): (WebCore::CCHeadsUpDisplay::drawFPSCounter): (WebCore::CCHeadsUpDisplay::drawFPSCounterText): (WebCore::CCHeadsUpDisplay::drawPlatformLayerTree): * platform/graphics/chromium/cc/CCHeadsUpDisplay.h: (WebCore::CCHeadsUpDisplay::create): (CCHeadsUpDisplay): * platform/graphics/chromium/cc/CCLayerTreeHost.cpp: (WebCore::CCLayerTreeHost::initialize): * platform/graphics/chromium/cc/CCLayerTreeHost.h: (WebCore): (WebCore::CCLayerTreeHost::headsUpDisplayFontAtlas): (CCLayerTreeHost): * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp: (WebCore::CCLayerTreeHostImpl::initializeLayerRenderer): * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h: (WebCore): (CCLayerTreeHostImpl): * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp: (WebCore::CCSingleThreadProxy::initializeLayerRenderer): (WebCore::CCSingleThreadProxy::recreateContext): * platform/graphics/chromium/cc/CCThreadProxy.cpp: (WebCore::CCThreadProxy::initializeLayerRendererOnImplThread): (WebCore::CCThreadProxy::recreateContextOnImplThread): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114147 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Source/WebCore/ChangeLog | 65 ++++++++ Source/WebCore/WebCore.gypi | 2 + .../graphics/chromium/LayerRendererChromium.cpp | 8 +- .../graphics/chromium/LayerRendererChromium.h | 5 +- .../platform/graphics/chromium/cc/CCFontAtlas.cpp | 175 +++++++++++++++++++++ .../platform/graphics/chromium/cc/CCFontAtlas.h | 92 +++++++++++ .../graphics/chromium/cc/CCHeadsUpDisplay.cpp | 81 ++-------- .../graphics/chromium/cc/CCHeadsUpDisplay.h | 19 +-- .../graphics/chromium/cc/CCLayerTreeHost.cpp | 7 + .../graphics/chromium/cc/CCLayerTreeHost.h | 6 + .../graphics/chromium/cc/CCLayerTreeHostImpl.cpp | 4 +- .../graphics/chromium/cc/CCLayerTreeHostImpl.h | 3 +- .../graphics/chromium/cc/CCSingleThreadProxy.cpp | 4 +- .../graphics/chromium/cc/CCThreadProxy.cpp | 4 +- 14 files changed, 386 insertions(+), 89 deletions(-) create mode 100644 Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp create mode 100644 Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index d21c96c..77f9481 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,68 @@ +2012-04-12 Shawn Singh + + [chromium] Support CCHeadsUpDisplay in threaded compositing mode + https://bugs.webkit.org/show_bug.cgi?id=67499 + + Reviewed by James Robinson. + + No new tests because this code is debugging code itself. + + The last item that was needed to make the CCHeadsUpDisplay work in + threaded compositing mode was to remove the font rendering code + used on the impl-side thread. To solve this, this patch adds a + CCFontAtlas that is initialized on the main thread (where the font + rendering takes place). Then, when the HUD draws text on the impl + thread, it uses the font atlas directly. + + * WebCore.gypi: + * platform/graphics/chromium/LayerRendererChromium.cpp: + (WebCore::LayerRendererChromium::create): + (WebCore::LayerRendererChromium::initialize): + * platform/graphics/chromium/LayerRendererChromium.h: + (WebCore): + (LayerRendererChromium): + * platform/graphics/chromium/cc/CCFontAtlas.cpp: Added. + (WebCore): + (WebCore::CCFontAtlas::CCFontAtlas): + (WebCore::wrapPositionIfNeeded): + (WebCore::CCFontAtlas::generateAtlasForFont): + (WebCore::CCFontAtlas::initialize): + (WebCore::CCFontAtlas::drawText): + (WebCore::CCFontAtlas::drawOneLineOfTextInternal): + (WebCore::CCFontAtlas::drawDebugAtlas): + * platform/graphics/chromium/cc/CCFontAtlas.h: Added. + (WebCore): + (CCFontAtlas): + (WebCore::CCFontAtlas::create): + * platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp: + (WebCore::CCHeadsUpDisplay::CCHeadsUpDisplay): + (WebCore): + (WebCore::CCHeadsUpDisplay::showPlatformLayerTree): + (WebCore::CCHeadsUpDisplay::drawHudContents): + (WebCore::CCHeadsUpDisplay::drawFPSCounter): + (WebCore::CCHeadsUpDisplay::drawFPSCounterText): + (WebCore::CCHeadsUpDisplay::drawPlatformLayerTree): + * platform/graphics/chromium/cc/CCHeadsUpDisplay.h: + (WebCore::CCHeadsUpDisplay::create): + (CCHeadsUpDisplay): + * platform/graphics/chromium/cc/CCLayerTreeHost.cpp: + (WebCore::CCLayerTreeHost::initialize): + * platform/graphics/chromium/cc/CCLayerTreeHost.h: + (WebCore): + (WebCore::CCLayerTreeHost::headsUpDisplayFontAtlas): + (CCLayerTreeHost): + * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp: + (WebCore::CCLayerTreeHostImpl::initializeLayerRenderer): + * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h: + (WebCore): + (CCLayerTreeHostImpl): + * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp: + (WebCore::CCSingleThreadProxy::initializeLayerRenderer): + (WebCore::CCSingleThreadProxy::recreateContext): + * platform/graphics/chromium/cc/CCThreadProxy.cpp: + (WebCore::CCThreadProxy::initializeLayerRendererOnImplThread): + (WebCore::CCThreadProxy::recreateContextOnImplThread): + 2012-04-13 Rob Flack Chromium: Should enable -webkit-image-set diff --git a/Source/WebCore/WebCore.gypi b/Source/WebCore/WebCore.gypi index f57f9cd..e00eeef 100644 --- a/Source/WebCore/WebCore.gypi +++ b/Source/WebCore/WebCore.gypi @@ -3607,6 +3607,8 @@ 'platform/graphics/chromium/cc/CCDelayBasedTimeSource.h', 'platform/graphics/chromium/cc/CCDrawQuad.cpp', 'platform/graphics/chromium/cc/CCDrawQuad.h', + 'platform/graphics/chromium/cc/CCFontAtlas.cpp', + 'platform/graphics/chromium/cc/CCFontAtlas.h', 'platform/graphics/chromium/cc/CCFrameRateController.cpp', 'platform/graphics/chromium/cc/CCFrameRateController.h', 'platform/graphics/chromium/cc/CCGestureCurve.h', diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 8d7ca26..e8f6a74 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -195,10 +195,10 @@ private: }; -PassOwnPtr LayerRendererChromium::create(LayerRendererChromiumClient* client, PassRefPtr context) +PassOwnPtr LayerRendererChromium::create(LayerRendererChromiumClient* client, PassRefPtr context, CCFontAtlas* headsUpDisplayFontAtlas) { OwnPtr layerRenderer(adoptPtr(new LayerRendererChromium(client, context))); - if (!layerRenderer->initialize()) + if (!layerRenderer->initialize(headsUpDisplayFontAtlas)) return nullptr; return layerRenderer.release(); @@ -237,7 +237,7 @@ private: LayerRendererChromiumClient* m_client; }; -bool LayerRendererChromium::initialize() +bool LayerRendererChromium::initialize(CCFontAtlas* headsUpDisplayFontAtlas) { if (!m_context->makeContextCurrent()) return false; @@ -307,7 +307,7 @@ bool LayerRendererChromium::initialize() if (!initializeSharedObjects()) return false; - m_headsUpDisplay = CCHeadsUpDisplay::create(this); + m_headsUpDisplay = CCHeadsUpDisplay::create(this, headsUpDisplayFontAtlas); // Make sure the viewport and context gets initialized, even if it is to zero. viewportChanged(); diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index d501531..a05f9fd 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -54,6 +54,7 @@ namespace WebCore { +class CCFontAtlas; class CCHeadsUpDisplay; class CCLayerImpl; class CCRenderPass; @@ -79,7 +80,7 @@ public: class LayerRendererChromium { WTF_MAKE_NONCOPYABLE(LayerRendererChromium); public: - static PassOwnPtr create(LayerRendererChromiumClient*, PassRefPtr); + static PassOwnPtr create(LayerRendererChromiumClient*, PassRefPtr, CCFontAtlas*); ~LayerRendererChromium(); @@ -173,7 +174,7 @@ protected: bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; } LayerRendererChromium(LayerRendererChromiumClient*, PassRefPtr); - bool initialize(); + bool initialize(CCFontAtlas* headsUpDisplayFontAtlas = 0); private: void drawQuad(const CCDrawQuad*, const FloatRect& surfaceDamageRect); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp new file mode 100644 index 0000000..5da4296 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "CCFontAtlas.h" + +#include "CCProxy.h" +#include "Font.h" +#include "FontCache.h" +#include "FontDescription.h" +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "TextRun.h" + +#define ATLAS_SIZE 128 +#define FONT_HEIGHT 14 + +namespace WebCore { + +using namespace std; + + +CCFontAtlas::CCFontAtlas() + : m_fontHeight(FONT_HEIGHT) +{ +} + +static void wrapPositionIfNeeded(IntPoint& position, int textWidth, int textHeight) +{ + if (position.x() + textWidth > ATLAS_SIZE) + position = IntPoint(0, position.y() + textHeight); +} + +void CCFontAtlas::generateAtlasForFont(GraphicsContext* atlasContext, const FontDescription& fontDescription, const Color& fontColor, const IntPoint& startingPosition, IntRect asciiToAtlasTable[128]) +{ + ASSERT(CCProxy::isMainThread()); + ASSERT(m_atlas); + + FontCachePurgePreventer fontCachePurgePreventer; + + IntPoint position = startingPosition; + int textHeight = fontDescription.computedPixelSize(); + // This is a dirty little trick to account for overhang letters like g, p, j. + int inflation = textHeight / 3; + + Font font(fontDescription, 0, 0); + font.update(0); + + atlasContext->setStrokeColor(fontColor, ColorSpaceDeviceRGB); + atlasContext->setFillColor(fontColor, ColorSpaceDeviceRGB); + + // First, draw a generic rect that will be used for special and unknown characters that have nothing else to render. + { + int textWidth = textHeight / 2; + wrapPositionIfNeeded(position, textWidth, textHeight + inflation); + atlasContext->strokeRect(FloatRect(FloatPoint(position.x() + 1, position.y() - textHeight + 1 + inflation), FloatSize(textWidth - 2, textHeight - 2 - inflation)), 1); + + // Initialize the rect that would be copied when drawing this glyph from the atlas. + asciiToAtlasTable[0] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation)); + + // Increment to the position where the next glyph will be placed. + position.setX(position.x() + textWidth); + } + + // Then, draw the ASCII characters. + for (LChar i = 1; i < 128; ++i) { + if (i < 32) { + // Special characters will simply use the the default glyph. + asciiToAtlasTable[i] = asciiToAtlasTable[0]; + continue; + } + + String str; + str.append(i); + TextRun text(str); + + int textWidth = round(font.width(text)); + wrapPositionIfNeeded(position, textWidth, textHeight + inflation); + atlasContext->drawText(font, text, position); + + // Initialize the rect that would be copied when drawing this glyph from the atlas. + asciiToAtlasTable[i] = IntRect(IntPoint(position.x(), position.y() - textHeight), IntSize(textWidth, textHeight + inflation)); + + // Increment to the position where the next glyph will be placed. + position.setX(position.x() + textWidth); + } +} + +void CCFontAtlas::initialize() +{ + ASSERT(CCProxy::isMainThread()); + + // We expect this function to be called only once when the atlas did not exist yet. We should be aware if that's not true. + ASSERT(!m_atlas); + + m_atlas = ImageBuffer::create(IntSize(ATLAS_SIZE, ATLAS_SIZE)); + GraphicsContext* atlasContext = m_atlas->context(); + + // Clear the entire texture atlas to transparent before drawing fonts. + atlasContext->setFillColor(Color(0, 0, 0, 0), ColorSpaceDeviceRGB); + atlasContext->fillRect(FloatRect(0, 0, ATLAS_SIZE, ATLAS_SIZE)); + + // FIXME: monospace font does not work as expected. + FontDescription fontDescription; + fontDescription.setGenericFamily(FontDescription::MonospaceFamily); + fontDescription.setComputedSize(m_fontHeight); + generateAtlasForFont(atlasContext, fontDescription, Color(255, 0, 0), IntPoint(0, fontDescription.computedPixelSize()), m_asciiToRectTable); +} + +void CCFontAtlas::drawText(GraphicsContext* targetContext, const String& text, const IntPoint& destPosition, const IntSize& clip) const +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_atlas); + + Vector lines; + text.split('\n', lines); + + IntPoint position = destPosition; + for (size_t i = 0; i < lines.size(); ++i) { + drawOneLineOfTextInternal(targetContext, lines[i], position); + position.setY(position.y() + m_fontHeight); + if (position.y() > clip.height()) + return; + } +} + +void CCFontAtlas::drawOneLineOfTextInternal(GraphicsContext* targetContext, const String& textLine, const IntPoint& destPosition) const +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_atlas); + + IntPoint position = destPosition; + for (unsigned i = 0; i < textLine.length(); ++i) { + // If the ASCII code is out of bounds, then index 0 is used, which is just a plain rectangle glyph. + int asciiIndex = (textLine[i] < 128) ? textLine[i] : 0; + IntRect glyphBounds = m_asciiToRectTable[asciiIndex]; + targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, position, glyphBounds); + position.setX(position.x() + glyphBounds.width()); + } +} + +void CCFontAtlas::drawDebugAtlas(GraphicsContext* targetContext, const IntPoint& destPosition) const +{ + ASSERT(CCProxy::isImplThread()); + ASSERT(m_atlas); + + targetContext->drawImageBuffer(m_atlas.get(), ColorSpaceDeviceRGB, destPosition, IntRect(IntPoint::zero(), IntSize(ATLAS_SIZE, ATLAS_SIZE))); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h new file mode 100644 index 0000000..cca3a1c --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCFontAtlas.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CCFontAtlas_h +#define CCFontAtlas_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "ImageBuffer.h" +#include +#include +#include + +namespace WebCore { + +class Color; +class FontDescription; +class IntPoint; +class IntRect; +class GraphicsContext; + +// This class provides basic ability to draw text onto the heads-up display. +// It must be initialized on the main thread, and it can only draw text on the impl thread. +class CCFontAtlas { + WTF_MAKE_NONCOPYABLE(CCFontAtlas); +public: + static PassOwnPtr create() + { + return adoptPtr(new CCFontAtlas()); + } + + // Creates the font atlas. + // - Should only be called on the main thread. + void initialize(); + + // Draws multiple lines of text where each line of text is separated by '\n'. + // - Correct glyphs will be drawn for ASCII codes in the range 32-127; any characters + // outside that range will be displayed as a default rectangle glyph. + // - IntSize clip is used to avoid wasting time drawing things that are outside the + // target canvas bounds. + // - Should only be called only on the impl thread. + void drawText(GraphicsContext*, const String& text, const IntPoint& destPosition, const IntSize& clip) const; + + // Draws the entire atlas at the specified position, just for debugging purposes. + void drawDebugAtlas(GraphicsContext*, const IntPoint& destPosition) const; + +private: + CCFontAtlas(); + + // Paints the font into the atlas, from left-to-right, top-to-bottom, starting at + // startingPosition. At the same time, it updates the ascii-to-IntRect mapping for + // each character. By doing things this way, it is possible to support variable-width + // fonts and multiple fonts on the same atlas. + void generateAtlasForFont(GraphicsContext*, const FontDescription&, const Color& fontColor, const IntPoint& startingPosition, IntRect asciiToAtlasTable[128]); + + void drawOneLineOfTextInternal(GraphicsContext*, const String&, const IntPoint& destPosition) const; + + // The actual texture atlas containing all the pre-rendered glyphs. + OwnPtr m_atlas; + + // The look-up tables mapping ascii characters to their IntRect locations on the atlas. + IntRect m_asciiToRectTable[128]; + + int m_fontHeight; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp index fe2e520..e2e214d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.cpp @@ -27,10 +27,8 @@ #if USE(ACCELERATED_COMPOSITING) #include "CCHeadsUpDisplay.h" +#include "CCFontAtlas.h" #include "Extensions3DChromium.h" -#include "Font.h" -#include "FontCache.h" -#include "FontDescription.h" #include "GraphicsContext3D.h" #include "InspectorController.h" #include "LayerChromium.h" @@ -48,20 +46,16 @@ namespace WebCore { using namespace std; -CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner) +CCHeadsUpDisplay::CCHeadsUpDisplay(LayerRendererChromium* owner, CCFontAtlas* headsUpDisplayFontAtlas) : m_currentFrameNumber(1) , m_layerRenderer(owner) , m_useMapSubForUploads(owner->contextSupportsMapSub()) + , m_fontAtlas(headsUpDisplayFontAtlas) { m_beginTimeHistoryInSec[0] = currentTime(); m_beginTimeHistoryInSec[1] = m_beginTimeHistoryInSec[0]; for (int i = 2; i < kBeginFrameHistorySize; i++) m_beginTimeHistoryInSec[i] = 0; - - // We can't draw text in threaded mode with the current mechanism. - // FIXME: Figure out a way to draw text in threaded mode. - if (!CCProxy::implThread()) - initializeFonts(); } CCHeadsUpDisplay::~CCHeadsUpDisplay() @@ -71,24 +65,6 @@ CCHeadsUpDisplay::~CCHeadsUpDisplay() const double CCHeadsUpDisplay::kIdleSecondsTriggersReset = 0.5; const double CCHeadsUpDisplay::kFrameTooFast = 1.0 / 70; -void CCHeadsUpDisplay::initializeFonts() -{ - ASSERT(!CCProxy::implThread()); - FontDescription mediumFontDesc; - mediumFontDesc.setGenericFamily(FontDescription::MonospaceFamily); - mediumFontDesc.setComputedSize(12); - - m_mediumFont = adoptPtr(new Font(mediumFontDesc, 0, 0)); - m_mediumFont->update(0); - - FontDescription smallFontDesc; - smallFontDesc.setGenericFamily(FontDescription::MonospaceFamily); - smallFontDesc.setComputedSize(10); - - m_smallFont = adoptPtr(new Font(smallFontDesc, 0, 0)); - m_smallFont->update(0); -} - // safeMod works on -1, returning m-1 in that case. static inline int safeMod(int number, int modulus) { @@ -117,7 +93,7 @@ bool CCHeadsUpDisplay::enabled() const bool CCHeadsUpDisplay::showPlatformLayerTree() const { - return settings().showPlatformLayerTree && !CCProxy::implThread(); + return settings().showPlatformLayerTree; } void CCHeadsUpDisplay::draw() @@ -204,9 +180,6 @@ void CCHeadsUpDisplay::drawHudContents(GraphicsContext* context, const IntSize& } int fpsCounterHeight = 40; - if (!CCProxy::implThread()) - fpsCounterHeight += m_mediumFont->fontMetrics().floatHeight(); - int fpsCounterTop = 2; int platformLayerTreeTop; if (settings().showFPSCounter) @@ -218,7 +191,7 @@ void CCHeadsUpDisplay::drawHudContents(GraphicsContext* context, const IntSize& drawFPSCounter(context, fpsCounterTop, fpsCounterHeight); if (showPlatformLayerTree()) - drawPlatformLayerTree(context, platformLayerTreeTop); + drawPlatformLayerTree(context, hudSize, platformLayerTreeTop); } void CCHeadsUpDisplay::getAverageFPSAndStandardDeviation(double *average, double *standardDeviation) const @@ -267,12 +240,12 @@ void CCHeadsUpDisplay::getAverageFPSAndStandardDeviation(double *average, double void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* context, int top, int height) { - float textWidth = 0; - if (!CCProxy::implThread()) - textWidth = drawFPSCounterText(context, top, height); - + float textWidth = 170; // so text fits on linux. float graphWidth = kBeginFrameHistorySize; + // Draw the FPS text. + drawFPSCounterText(context, top, textWidth, height); + // Draw FPS graph. const double loFPS = 0; const double hiFPS = 80; @@ -308,46 +281,24 @@ void CCHeadsUpDisplay::drawFPSCounter(GraphicsContext* context, int top, int hei } } -float CCHeadsUpDisplay::drawFPSCounterText(GraphicsContext* context, int top, int height) +void CCHeadsUpDisplay::drawFPSCounterText(GraphicsContext* context, int top, int width, int height) { - ASSERT(!CCProxy::implThread()); - - FontCachePurgePreventer fontCachePurgePreventer; double averageFPS, stdDeviation; - getAverageFPSAndStandardDeviation(&averageFPS, &stdDeviation); - String fps(String::format("FPS: %4.1f +/-%3.1f", averageFPS, stdDeviation)); - TextRun text(fps); - float textWidth = m_mediumFont->width(text) + 2; - // Draw background. context->setFillColor(Color(0, 0, 0, 255), ColorSpaceDeviceRGB); - double fontHeight = m_mediumFont->fontMetrics().floatHeight() + 2; - context->fillRect(FloatRect(2, top, textWidth, fontHeight)); + context->fillRect(FloatRect(2, top, width, height)); // Draw FPS text. - context->setFillColor(Color(200, 200, 200), ColorSpaceDeviceRGB); - context->drawText(*m_mediumFont, text, IntPoint(3, top + fontHeight - 4)); - - return textWidth; + if (m_fontAtlas) + m_fontAtlas->drawText(context, String::format("FPS: %4.1f +/- %3.1f", averageFPS, stdDeviation), IntPoint(10, height / 3), IntSize(width, height)); } -void CCHeadsUpDisplay::drawPlatformLayerTree(GraphicsContext* context, int top) +void CCHeadsUpDisplay::drawPlatformLayerTree(GraphicsContext* context, const IntSize hudSize, int top) { - ASSERT(!CCProxy::implThread()); - - FontCachePurgePreventer fontCachePurgePreventer; - - float smallFontHeight = m_smallFont->fontMetrics().floatHeight(); - int y = top + smallFontHeight - 4; - context->setFillColor(Color(255, 0, 0), ColorSpaceDeviceRGB); - Vector lines; - m_layerRenderer->layerTreeAsText().split('\n', lines); - for (size_t i = 0; i < lines.size(); ++i) { - context->drawText(*m_smallFont, TextRun(lines[i]), IntPoint(2, y)); - y += smallFontHeight; - } + if (m_fontAtlas) + m_fontAtlas->drawText(context, m_layerRenderer->layerTreeAsText(), IntPoint(2, top), hudSize); } const CCSettings& CCHeadsUpDisplay::settings() const diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h index f9659fd..200ea06 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCHeadsUpDisplay.h @@ -27,7 +27,7 @@ #if USE(ACCELERATED_COMPOSITING) -#include "Font.h" +#include "CCFontAtlas.h" #include "ProgramBinding.h" #include "ShaderChromium.h" @@ -43,9 +43,9 @@ class ManagedTexture; class CCHeadsUpDisplay { WTF_MAKE_NONCOPYABLE(CCHeadsUpDisplay); public: - static PassOwnPtr create(LayerRendererChromium* owner) + static PassOwnPtr create(LayerRendererChromium* owner, CCFontAtlas* headsUpDisplayFontAtlas) { - return adoptPtr(new CCHeadsUpDisplay(owner)); + return adoptPtr(new CCHeadsUpDisplay(owner, headsUpDisplayFontAtlas)); } ~CCHeadsUpDisplay(); @@ -61,11 +61,11 @@ public: typedef ProgramBinding Program; private: - explicit CCHeadsUpDisplay(LayerRendererChromium* owner); + CCHeadsUpDisplay(LayerRendererChromium* owner, CCFontAtlas* headsUpDisplayFontAtlas); void drawHudContents(GraphicsContext*, const IntSize& hudSize); void drawFPSCounter(GraphicsContext*, int top, int height); - float drawFPSCounterText(GraphicsContext*, int top, int height); - void drawPlatformLayerTree(GraphicsContext*, int top); + void drawFPSCounterText(GraphicsContext*, int top, int width, int height); + void drawPlatformLayerTree(GraphicsContext*, const IntSize hudSize, int top); const CCSettings& settings() const; bool isBadFrame(int frameNumber) const; int frameIndex(int frameNumber) const; @@ -73,8 +73,6 @@ private: bool showPlatformLayerTree() const; - void initializeFonts(); - int m_currentFrameNumber; OwnPtr m_hudTexture; @@ -89,10 +87,9 @@ private: static const double kFrameTooFast; static const int kNumMissedFramesForReset = 5; - OwnPtr m_smallFont; - OwnPtr m_mediumFont; - bool m_useMapSubForUploads; + + CCFontAtlas* m_fontAtlas; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp index 8d47a79..d6e1fe2 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp @@ -32,6 +32,7 @@ #include "Region.h" #include "TraceEvent.h" #include "TreeSynchronizer.h" +#include "cc/CCFontAtlas.h" #include "cc/CCLayerAnimationController.h" #include "cc/CCLayerIterator.h" #include "cc/CCLayerTreeHostCommon.h" @@ -99,6 +100,12 @@ bool CCLayerTreeHost::initialize() if (!m_proxy->initializeContext()) return false; + // Only allocate the font atlas if we have reason to use the heads-up display. + if (m_settings.showFPSCounter || m_settings.showPlatformLayerTree) { + m_headsUpDisplayFontAtlas = CCFontAtlas::create(); + m_headsUpDisplayFontAtlas->initialize(); + } + m_compositorIdentifier = m_proxy->compositorIdentifier(); return true; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h index f7889fd..e0c211b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h @@ -43,6 +43,7 @@ namespace WebCore { +class CCFontAtlas; class CCLayerTreeHostImpl; class CCLayerTreeHostImplClient; class CCTextureUpdater; @@ -220,6 +221,8 @@ public: bool requestPartialTextureUpdate(); void deleteTextureAfterCommit(PassOwnPtr); + CCFontAtlas* headsUpDisplayFontAtlas() { return m_headsUpDisplayFontAtlas.get(); } + protected: CCLayerTreeHost(CCLayerTreeHostClient*, const CCSettings&); bool initialize(); @@ -263,6 +266,9 @@ private: CCSettings m_settings; + // This is owned by the main layer tree host because it needs to be initialized on the main thread. + OwnPtr m_headsUpDisplayFontAtlas; + IntSize m_viewportSize; bool m_visible; typedef HashMap > RateLimiterMap; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp index 2e90c0f..60fd5fe 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp @@ -497,10 +497,10 @@ void CCLayerTreeHostImpl::setVisible(bool visible) m_timeSourceClientAdapter->setActive(shouldTickInBackground); } -bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr context) +bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr context, CCFontAtlas* headsUpDisplayFontAtlas) { OwnPtr layerRenderer; - layerRenderer = LayerRendererChromium::create(this, context); + layerRenderer = LayerRendererChromium::create(this, context, headsUpDisplayFontAtlas); // Since we now have a new context/layerRenderer, we cannot continue to use the old // resources (i.e. renderSurfaces and texture IDs). diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h index f455915..0cb0824 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h @@ -40,6 +40,7 @@ namespace WebCore { class CCActiveGestureAnimation; class CCCompletionEvent; +class CCFontAtlas; class CCPageScaleAnimation; class CCLayerImpl; class CCLayerTreeHostImplTimeSourceAdapter; @@ -109,7 +110,7 @@ public: void finishAllRendering(); int frameNumber() const { return m_frameNumber; } - bool initializeLayerRenderer(PassRefPtr); + bool initializeLayerRenderer(PassRefPtr, CCFontAtlas* headsUpDisplayFontAtlas = 0); bool isContextLost(); LayerRendererChromium* layerRenderer() { return m_layerRenderer.get(); } const LayerRendererCapabilities& layerRendererCapabilities() const; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp index 3e53efe..b139cd4 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp @@ -132,7 +132,7 @@ bool CCSingleThreadProxy::initializeLayerRenderer() ASSERT(m_contextBeforeInitialization); { DebugScopedSetImplThread impl; - bool ok = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitialization.release()); + bool ok = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitialization.release(), m_layerTreeHost->headsUpDisplayFontAtlas()); if (ok) { m_layerRendererInitialized = true; m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities(); @@ -156,7 +156,7 @@ bool CCSingleThreadProxy::recreateContext() { DebugScopedSetImplThread impl; m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); - initialized = m_layerTreeHostImpl->initializeLayerRenderer(context); + initialized = m_layerTreeHostImpl->initializeLayerRenderer(context, m_layerTreeHost->headsUpDisplayFontAtlas()); if (initialized) { m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities(); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp index 638ecd2..20325ef 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp @@ -716,7 +716,7 @@ void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* compl TRACE_EVENT("CCThreadProxy::initializeLayerRendererOnImplThread", this, 0); ASSERT(isImplThread()); ASSERT(m_contextBeforeInitializationOnImplThread); - *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release()); + *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release(), m_layerTreeHost->headsUpDisplayFontAtlas()); if (*initializeSucceeded) { *capabilities = m_layerTreeHostImpl->layerRendererCapabilities(); if (capabilities->usingSwapCompleteCallback) @@ -753,7 +753,7 @@ void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, G TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread"); ASSERT(isImplThread()); m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); - *recreateSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(adoptRef(contextPtr)); + *recreateSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(adoptRef(contextPtr), m_layerTreeHost->headsUpDisplayFontAtlas()); if (*recreateSucceeded) { *capabilities = m_layerTreeHostImpl->layerRendererCapabilities(); m_schedulerOnImplThread->didRecreateContext(); -- 2.7.4