diff options
Diffstat (limited to 'Source')
30 files changed, 706 insertions, 156 deletions
diff --git a/Source/WebCore/platform/android/RenderThemeAndroid.cpp b/Source/WebCore/platform/android/RenderThemeAndroid.cpp index 481ecbf..93c99a4 100644 --- a/Source/WebCore/platform/android/RenderThemeAndroid.cpp +++ b/Source/WebCore/platform/android/RenderThemeAndroid.cpp @@ -428,6 +428,7 @@ static void adjustMenuListStyleCommon(RenderStyle* style) style->setPaddingTop(Length(RenderSkinCombo::padding(), Fixed)); style->setPaddingBottom(Length(RenderSkinCombo::padding(), Fixed)); style->setPaddingRight(Length(RenderSkinCombo::extraWidth(), Fixed)); + style->setMinHeight(Length(RenderSkinCombo::minHeight(), Fixed)); } void RenderThemeAndroid::adjustListboxStyle(CSSStyleSelector*, RenderStyle* style, Element*) const diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index a7fe030..7c7b937 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -101,13 +101,14 @@ void BaseLayerAndroid::setContent(const PictureSet& src) // setSize(src.width(), src.height()); } -void BaseLayerAndroid::drawCanvas(SkCanvas* canvas) +bool BaseLayerAndroid::drawCanvas(SkCanvas* canvas) { #if USE(ACCELERATED_COMPOSITING) android::Mutex::Autolock lock(m_drawLock); #endif if (!m_content.isEmpty()) m_content.draw(canvas); + return true; } #if USE(ACCELERATED_COMPOSITING) @@ -307,16 +308,6 @@ bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot, m_glWebViewState->resetFrameworkInval(); if (compositedRoot) { - TransformationMatrix ident; - - bool animsRunning = compositedRoot->evaluateAnimations(); - if (animsRunning) - needsRedraw = true; - - compositedRoot->updateFixedLayersPositions(visibleRect); - FloatRect clip(0, 0, viewRect.width(), viewRect.height()); - compositedRoot->updateGLPositionsAndScale( - ident, clip, 1, m_glWebViewState->zoomManager()->layersScale()); SkMatrix matrix; matrix.setTranslate(viewRect.x(), viewRect.y()); @@ -326,20 +317,16 @@ bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot, compositedRoot->nbLayers(), compositedRoot->nbTexturedLayers()); #endif - - // Clean up GL textures for video layer. - TilesManager::instance()->videoLayerManager()->deleteUnusedTextures(); - - compositedRoot->prepare(m_glWebViewState); - if (compositedRoot->drawGL(m_glWebViewState, matrix)) { + // For now, we render layers only if the rendering mode + // is kAllTextures or kClippedTextures + if (m_glWebViewState->layersRenderingMode() < GLWebViewState::kScrollableAndFixedLayers + && compositedRoot->drawGL(m_glWebViewState, matrix)) { if (TilesManager::instance()->layerTexturesRemain()) { // only try redrawing for layers if layer textures remain, // otherwise we'll repaint without getting anything done needsRedraw = true; } - } else if (!animsRunning) - m_glWebViewState->resetLayersDirtyArea(); - + } } m_previousVisible = visibleRect; diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h index ad77013..20942ec 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h @@ -58,7 +58,7 @@ public: // the passed canvas. We used it to paint the GL tiles as well as // WebView::copyBaseContentToPicture(), so a lock is necessary as // we are running in different threads. - void drawCanvas(SkCanvas* canvas); + virtual bool drawCanvas(SkCanvas* canvas); bool drawGL(double currentTime, LayerAndroid* compositedRoot, IntRect& rect, SkRect& viewport, float scale, bool* buffersSwappedPtr); diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp index 13d276a..852413f 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp @@ -59,6 +59,9 @@ using namespace android; namespace WebCore { +typedef std::pair<int, float> FallbackFontKey; +typedef HashMap<FallbackFontKey, FontPlatformData*> FallbackHash; + static void updateForFont(SkPaint* paint, const SimpleFontData* font) { font->platformData().setupPaint(paint); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); @@ -456,7 +459,6 @@ private: }; static const char* paths[NUM_SCRIPTS]; - static const FontPlatformData* s_fallbackPlatformData[NUM_SCRIPTS]; void setupFontForScriptRun(); const FontPlatformData* setupComplexFont(CustomScript script, @@ -514,9 +516,6 @@ const char* TextRunWalker::paths[] = { "/system/fonts/DroidSansThai.ttf" }; -// Indexed using enum CustomScript -const FontPlatformData* TextRunWalker::s_fallbackPlatformData[] = {}; - TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, unsigned startingY, const Font* font) : m_font(font) , m_startingX(startingX) @@ -674,17 +673,23 @@ const FontPlatformData* TextRunWalker::setupComplexFont( CustomScript script, const FontPlatformData& platformData) { - if (!s_fallbackPlatformData[script]) { + static FallbackHash fallbackPlatformData; + + FallbackFontKey key(script, platformData.size()); + FontPlatformData* newPlatformData = 0; + + if (!fallbackPlatformData.contains(key)) { SkTypeface* typeface = SkTypeface::CreateFromFile(paths[script]); - s_fallbackPlatformData[script] = new FontPlatformData(platformData, typeface); + newPlatformData = new FontPlatformData(platformData, typeface); SkSafeUnref(typeface); + fallbackPlatformData.set(key, newPlatformData); } - // If we couldn't allocate a new FontPlatformData, revert to the one passed - if (!s_fallbackPlatformData[script]) - return &platformData; + if (!newPlatformData) + newPlatformData = fallbackPlatformData.get(key); - return s_fallbackPlatformData[script]; + // If we couldn't allocate a new FontPlatformData, revert to the one passed + return newPlatformData ? newPlatformData : &platformData; } void TextRunWalker::setupFontForScriptRun() @@ -730,6 +735,16 @@ void TextRunWalker::setupFontForScriptRun() } m_item.face = complexPlatformData->harfbuzzFace(); m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData); + + int size = complexPlatformData->size(); + m_item.font->x_ppem = size; + m_item.font->y_ppem = size; + // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format. + const int devicePixelFraction = 64; + const int multiplyFor16Dot16 = 1 << 16; + int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits(); + m_item.font->x_scale = scale; + m_item.font->y_scale = scale; } HB_FontRec* TextRunWalker::allocHarfbuzzFont() @@ -738,13 +753,6 @@ HB_FontRec* TextRunWalker::allocHarfbuzzFont() memset(font, 0, sizeof(HB_FontRec)); font->klass = &harfbuzzSkiaClass; font->userData = 0; - // The values which harfbuzzSkiaClass returns are already scaled to - // pixel units, so we just set all these to one to disable further - // scaling. - font->x_ppem = 1; - font->y_ppem = 1; - font->x_scale = 1; - font->y_scale = 1; return font; } @@ -818,7 +826,9 @@ void TextRunWalker::setGlyphPositions(bool isRTL) int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; m_glyphs16[i] = m_item.glyphs[i]; - m_positions[i].set(SkIntToScalar(m_offsetX + position), m_startingY + SkIntToScalar(m_item.offsets[i].y)); + int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y); + m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY); int advance = truncateFixedPointToInteger(m_item.advances[i]); // The first half of the conjunction works around the case where diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h index 5c3313e..1e46971 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h @@ -82,6 +82,7 @@ public: float size() const { return mTextSize; } unsigned hash() const; + int emSizeInFontUnits() const; bool isFixedPitch() const; #ifndef NDEBUG @@ -113,6 +114,7 @@ private: SkTypeface* mTypeface; float mTextSize; + mutable int mEmSizeInFontUnits; bool mFakeBold; bool mFakeItalic; FontOrientation mOrientation; diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp index 3c90246..c09120f 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp @@ -33,6 +33,7 @@ #ifdef SUPPORT_COMPLEX_SCRIPTS #include "HarfbuzzSkia.h" #endif +#include "SkAdvancedTypefaceMetrics.h" #include "SkPaint.h" #include "SkTypeface.h" @@ -74,7 +75,7 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() } FontPlatformData::FontPlatformData() - : mTypeface(NULL), mTextSize(0), mFakeBold(false), mFakeItalic(false), + : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); @@ -87,10 +88,10 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) SkSafeRef(src.mTypeface); } - mTypeface = src.mTypeface; - - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; + mTypeface = src.mTypeface; + mTextSize = src.mTextSize; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; @@ -102,7 +103,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) - : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic), + : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), mOrientation(orientation), mTextOrientation(textOrientation) { if (hashTableDeletedFontValue() != mTypeface) { @@ -114,7 +115,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold } FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) - : mTypeface(src.mTypeface), mTextSize(textSize), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), + : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), m_harfbuzzFace(src.m_harfbuzzFace), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) { if (hashTableDeletedFontValue() != mTypeface) { @@ -126,7 +127,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) } FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) - : mTypeface(NULL), mTextSize(size), mFakeBold(bold), mFakeItalic(oblique), + : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); @@ -134,7 +135,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) } FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) - : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold), + : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) { @@ -158,6 +159,22 @@ FontPlatformData::~FontPlatformData() } } +int FontPlatformData::emSizeInFontUnits() const +{ + if (mEmSizeInFontUnits) + return mEmSizeInFontUnits; + + SkAdvancedTypefaceMetrics* metrics = 0; + if (mTypeface) + metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); + if (metrics) { + mEmSizeInFontUnits = metrics->fEmSize; + metrics->unref(); + } else + mEmSizeInFontUnits = 1000; // default value copied from Skia. + return mEmSizeInFontUnits; +} + FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) { if (hashTableDeletedFontValue() != src.mTypeface) { @@ -167,9 +184,10 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) SkSafeUnref(mTypeface); } - mTypeface = src.mTypeface; - mTextSize = src.mTextSize; - mFakeBold = src.mFakeBold; + mTypeface = src.mTypeface; + mEmSizeInFontUnits = src.mEmSizeInFontUnits; + mTextSize = src.mTextSize; + mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 09e8cc4..e997b57 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -33,11 +33,14 @@ #include "GLUtils.h" #include "ImagesManager.h" #include "LayerAndroid.h" +#include "ScrollableLayerAndroid.h" #include "SkPath.h" #include "TilesManager.h" #include "TilesTracker.h" #include <wtf/CurrentTime.h> +#include <pthread.h> + #include <cutils/log.h> #include <wtf/text/CString.h> @@ -86,6 +89,7 @@ GLWebViewState::GLWebViewState() , m_expandedTileBoundsX(0) , m_expandedTileBoundsY(0) , m_scale(1) + , m_layersRenderingMode(kAllTextures) { m_viewport.setEmpty(); m_futureViewportTileBounds.setEmpty(); @@ -151,7 +155,6 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval SkSafeUnref(m_currentBaseLayer); m_currentBaseLayer = layer; - // copy content from old composited root to new LayerAndroid* oldRoot = m_currentBaseLayerRoot; if (layer) { @@ -173,7 +176,13 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval m_paintingBaseLayer = layer; } m_glExtras.setDrawExtra(0); - invalRegion(inval); + + // TODO: do the union of both layers tree to compute + // the minimum inval instead of doing a fullInval() + if (m_layersRenderingMode == kSingleSurfaceRendering) + fullInval(); + else + invalRegion(inval); #ifdef MEASURES_PERF if (m_measurePerfs && !showVisualIndicator) @@ -184,6 +193,14 @@ void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval TilesManager::instance()->setShowVisualIndicator(showVisualIndicator); } +void GLWebViewState::scrolledLayer(ScrollableLayerAndroid*) +{ + // TODO: only inval the area of the scrolled layer instead of + // doing a fullInval() + if (m_layersRenderingMode == kSingleSurfaceRendering) + fullInval(); +} + void GLWebViewState::invalRegion(const SkRegion& region) { SkRegion::Iterator iterator(region); @@ -241,6 +258,11 @@ unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas) m_baseLayerLock.unlock(); if (base) { base->drawCanvas(canvas); + if (m_layersRenderingMode == kSingleSurfaceRendering) { + LayerAndroid* rootLayer = static_cast<LayerAndroid*>(base->getChild(0)); + if (rootLayer) + rootLayer->drawCanvas(canvas); + } } SkSafeUnref(base); return m_currentPictureCounter; @@ -402,6 +424,69 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect, return currentTime; } +bool GLWebViewState::setLayersRenderingMode(TexturesResult& nbTexturesNeeded) +{ + bool invalBase = false; + int maxTextures = TilesManager::instance()->maxTextureCount(); + LayersRenderingMode layersRenderingMode = m_layersRenderingMode; + + m_layersRenderingMode = kSingleSurfaceRendering; + if (nbTexturesNeeded.fixed < maxTextures) + m_layersRenderingMode = kFixedLayers; + if (nbTexturesNeeded.scrollable < maxTextures) + m_layersRenderingMode = kScrollableAndFixedLayers; + if (nbTexturesNeeded.clipped < maxTextures) + m_layersRenderingMode = kClippedTextures; + if (nbTexturesNeeded.full < maxTextures) + m_layersRenderingMode = kAllTextures; + + if (m_layersRenderingMode < layersRenderingMode + && m_layersRenderingMode != kAllTextures) + invalBase = true; + + if (m_layersRenderingMode > layersRenderingMode + && m_layersRenderingMode != kClippedTextures) + invalBase = true; + +#ifdef DEBUG + if (m_layersRenderingMode != layersRenderingMode) { + char* mode[] = { "kAllTextures", "kClippedTextures", + "kScrollableAndFixedLayers", "kFixedLayers", "kSingleSurfaceRendering" }; + XLOGC("Change from mode %s to %s -- We need textures: fixed: %d," + " scrollable: %d, clipped: %d, full: %d, max textures: %d", + static_cast<char*>(mode[layersRenderingMode]), + static_cast<char*>(mode[m_layersRenderingMode]), + nbTexturesNeeded.fixed, + nbTexturesNeeded.scrollable, + nbTexturesNeeded.clipped, + nbTexturesNeeded.full, maxTextures); + } +#endif + + // For now, anything below kClippedTextures is equivalent + // to kSingleSurfaceRendering + // TODO: implement the other rendering modes + if (m_layersRenderingMode > kClippedTextures) + m_layersRenderingMode = kSingleSurfaceRendering; + + // update the base surface if needed + if (m_layersRenderingMode != layersRenderingMode + && invalBase) { + m_tiledPageA->discardTextures(); + m_tiledPageB->discardTextures(); + fullInval(); + return true; + } + return false; +} + +void GLWebViewState::fullInval() +{ + // TODO -- use base layer's size. + IntRect ir(0, 0, 1E6, 1E6); + inval(ir); +} + bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, IntRect& clip, float scale, bool* buffersSwappedPtr) @@ -475,10 +560,45 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, // set up zoom manager, shaders, etc. m_backgroundColor = baseLayer->getBackgroundColor(); double currentTime = setupDrawing(rect, viewport, webViewRect, titleBarHeight, clip, scale); + + if (compositedRoot) + compositedRoot->setState(this); + + bool animsRunning = false; + TexturesResult nbTexturesNeeded; + if (compositedRoot) { + TransformationMatrix ident; + animsRunning = compositedRoot->evaluateAnimations(); + bool hasFixedElements = compositedRoot->updateFixedLayersPositions(viewport); + if (m_layersRenderingMode == kSingleSurfaceRendering) { + // If we are in single surface rendering, we may have to fully + // invalidate if we have fixed elements or if we have CSS + // animations. + // TODO: compute the minimum invals + if (animsRunning || hasFixedElements) + fullInval(); + } + + // TODO: get the base document area for the original clip + FloatRect clip(0, 0, 1E6, 1E6); + compositedRoot->updateGLPositionsAndScale(ident, clip, 1, zoomManager()->layersScale()); + compositedRoot->prepare(this); + + ret |= animsRunning; + + compositedRoot->computeTexturesAmount(&nbTexturesNeeded); + } + ret |= setLayersRenderingMode(nbTexturesNeeded); + + // Clean up GL textures for video layer. + TilesManager::instance()->videoLayerManager()->deleteUnusedTextures(); + ret |= baseLayer->drawGL(currentTime, compositedRoot, rect, viewport, scale, buffersSwappedPtr); + FloatRect extrasclip(0, 0, rect.width(), rect.height()); TilesManager::instance()->shader()->clip(extrasclip); + m_glExtras.drawGL(webViewRect, viewport, titleBarHeight); glBindBuffer(GL_ARRAY_BUFFER, 0); @@ -543,6 +663,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, TilesManager::instance()->getTilesTracker()->showTrackTextures(); ImagesManager::instance()->showImages(); #endif + return ret; } diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 5f7ca71..a1adaf1 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -57,6 +57,8 @@ namespace WebCore { class BaseLayerAndroid; class LayerAndroid; +class ScrollableLayerAndroid; +class TexturesResult; ///////////////////////////////////////////////////////////////////////////////// // GL Architecture @@ -208,6 +210,9 @@ public: int titleBarHeight, IntRect& screenClip, float scale); + bool setLayersRenderingMode(TexturesResult&); + void fullInval(); + bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, IntRect& clip, float scale, bool* buffersSwappedPtr); @@ -232,6 +237,18 @@ public: float scale() { return m_scale; } + enum LayersRenderingMode { + kAllTextures = 0, // all layers are drawn with textures fully covering them + kClippedTextures = 1, // all layers are drawn, but their textures will be clipped + kScrollableAndFixedLayers = 2, // only scrollable and fixed layers will be drawn + kFixedLayers = 3, // only fixed layers will be drawn + kSingleSurfaceRendering = 4 // no layers will be drawn on separate textures + // -- everything is drawn on the base surface. + }; + + LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; } + void scrolledLayer(ScrollableLayerAndroid*); + private: void inval(const IntRect& rect); // caller must hold m_baseLayerLock void invalRegion(const SkRegion& region); @@ -276,6 +293,8 @@ private: int m_expandedTileBoundsY; float m_scale; + + LayersRenderingMode m_layersRenderingMode; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index 05a0fdc..3e062f8 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -564,6 +564,7 @@ bool GraphicsLayerAndroid::repaint() phase.set(GraphicsLayerPaintBackground); if (!paintContext(m_contentLayer->recordContext(), layerBounds)) return false; + m_contentLayer->checkTextPresence(); // Construct the foreground layer and draw. RenderBox* box = layer->renderBox(); @@ -582,6 +583,7 @@ bool GraphicsLayerAndroid::repaint() layer->scrollToOffset(0, 0); // At this point, it doesn't matter if painting failed. (void) paintContext(m_foregroundLayer->recordContext(), contentsRect); + m_foregroundLayer->checkTextPresence(); layer->scrollToOffset(scroll.width(), scroll.height()); // Construct the clip layer for masking the contents. @@ -607,6 +609,7 @@ bool GraphicsLayerAndroid::repaint() // picture. if (!paintContext(m_contentLayer->recordContext(), layerBounds)) return false; + m_contentLayer->checkTextPresence(); // Check for a scrollable iframe and report the scrolling // limits based on the view size. if (m_contentLayer->contentIsScrollable()) { diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h index c8bb81d..89e101c 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/Layer.h @@ -122,6 +122,7 @@ public: // paint method + virtual bool drawCanvas(SkCanvas*) { return false; } void draw(SkCanvas*, SkScalar opacity); void draw(SkCanvas* canvas) { this->draw(canvas, SK_Scalar1); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index e0898e6..12a11bf 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -55,6 +55,87 @@ private: int m_opacity; }; +class HasTextBounder : public SkBounder { + virtual bool onIRect(const SkIRect& rect) + { + return false; + } +}; + +class HasTextCanvas : public SkCanvas { +public: + HasTextCanvas(SkBounder* bounder, SkPicture* picture) + : m_picture(picture) + , m_hasText(false) + { + setBounder(bounder); + } + + void setHasText() + { + m_hasText = true; + m_picture->abortPlayback(); + } + + bool hasText() + { + return m_hasText; + } + + virtual bool clipPath(const SkPath&, SkRegion::Op) { + return true; + } + + virtual void commonDrawBitmap(const SkBitmap& bitmap, + const SkIRect* rect, + const SkMatrix&, + const SkPaint&) {} + + virtual void drawPaint(const SkPaint& paint) {} + virtual void drawPath(const SkPath&, const SkPaint& paint) {} + virtual void drawPoints(PointMode, size_t, + const SkPoint [], const SkPaint& paint) {} + + virtual void drawRect(const SkRect& , const SkPaint& paint) {} + virtual void drawSprite(const SkBitmap& , int , int , + const SkPaint* paint = NULL) {} + + virtual void drawText(const void*, size_t byteLength, SkScalar, + SkScalar, const SkPaint& paint) + { + setHasText(); + } + + virtual void drawPosText(const void* , size_t byteLength, + const SkPoint [], const SkPaint& paint) + { + setHasText(); + } + + virtual void drawPosTextH(const void*, size_t byteLength, + const SkScalar [], SkScalar, + const SkPaint& paint) + { + setHasText(); + } + + virtual void drawTextOnPath(const void*, size_t byteLength, + const SkPath&, const SkMatrix*, + const SkPaint& paint) + { + setHasText(); + } + + virtual void drawPicture(SkPicture& picture) { + SkCanvas::drawPicture(picture); + } + +private: + + SkPicture* m_picture; + bool m_hasText; +}; + /////////////////////////////////////////////////////////////////////////////// LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), @@ -75,7 +156,9 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_scale(1), m_lastComputeTextureSize(0), m_owningLayer(owner), - m_type(LayerAndroid::WebCoreLayer) + m_type(LayerAndroid::WebCoreLayer), + m_state(0), + m_hasText(true) { m_backgroundColor = 0; @@ -97,7 +180,9 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_imageTexture(0), m_requestSent(false), m_owningLayer(layer.m_owningLayer), - m_type(LayerAndroid::UILayer) + m_type(LayerAndroid::UILayer), + m_state(0), + m_hasText(true) { m_isFixed = layer.m_isFixed; m_imageRef = layer.m_imageRef; @@ -141,12 +226,31 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_animations.add(key, (it->second)->copy()); } + m_hasText = layer.m_hasText; + #ifdef DEBUG_COUNT ClassTracker::instance()->increment("LayerAndroid - recopy (UI?)"); ClassTracker::instance()->add(this); #endif } +void LayerAndroid::checkTextPresence() +{ + if (m_recordingPicture) { + // Let's check if we have text or not. If we don't, we can limit + // ourselves to scale 1! + HasTextBounder hasTextBounder; + HasTextCanvas checker(&hasTextBounder, m_recordingPicture); + SkBitmap bitmap; + bitmap.setConfig(SkBitmap::kARGB_8888_Config, + m_recordingPicture->width(), + m_recordingPicture->height()); + checker.setBitmapDevice(bitmap); + checker.drawPicture(*m_recordingPicture); + m_hasText = checker.hasText(); + } +} + LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_haveClip(false), m_isFixed(false), @@ -160,7 +264,9 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_scale(1), m_lastComputeTextureSize(0), m_owningLayer(0), - m_type(LayerAndroid::NavCacheLayer) + m_type(LayerAndroid::NavCacheLayer), + m_state(0), + m_hasText(true) { m_backgroundColor = 0; m_dirty = false; @@ -234,7 +340,8 @@ void LayerAndroid::addDirtyArea(GLWebViewState* glWebViewState) IntSize layerSize(getSize().width(), getSize().height()); FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize); - FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(m_clippingRect); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect); + FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(clippingRect); area.intersect(clip); IntRect dirtyArea(area.x(), area.y(), area.width(), area.height()); @@ -489,8 +596,9 @@ const LayerAndroid* LayerAndroid::find(int* xPtr, int* yPtr, SkPicture* root) co /////////////////////////////////////////////////////////////////////////////// -void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer) +bool LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* parentIframeLayer) { + bool hasFixedElements = false; XLOG("updating fixed positions, using viewport %fx%f - %fx%f", viewport.fLeft, viewport.fTop, viewport.width(), viewport.height()); @@ -509,6 +617,7 @@ void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* par } if (m_isFixed) { + hasFixedElements = true; // So if this is a fixed layer inside a iframe, use the iframe offset // and the iframe's size as the viewport and pass to the children if (parentIframeLayer) { @@ -546,7 +655,9 @@ void LayerAndroid::updateFixedLayersPositions(SkRect viewport, LayerAndroid* par int count = this->countChildren(); for (int i = 0; i < count; i++) - this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer); + hasFixedElements |= this->getChild(i)->updateFixedLayersPositions(viewport, parentIframeLayer); + + return hasFixedElements; } void LayerAndroid::updatePositions() @@ -614,9 +725,9 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM setDrawOpacity(opacity); if (m_haveClip) { - // The clipping rect calculation and intersetion will be done in Screen Coord now. - FloatRect clip = - TilesManager::instance()->shader()->rectInScreenCoord(m_drawTransform, layerSize); + // The clipping rect calculation and intersetion will be done in documents coordinates. + FloatRect rect(0, 0, layerSize.width(), layerSize.height()); + FloatRect clip = m_drawTransform.mapRect(rect); clip.intersect(clipping); setDrawClip(clip); } else { @@ -707,6 +818,15 @@ int LayerAndroid::nbTexturedLayers() return nb; } +void LayerAndroid::computeTexturesAmount(TexturesResult* result) +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->computeTexturesAmount(result); + if (m_texture && m_visible) + m_texture->computeTexturesAmount(result); +} + void LayerAndroid::showLayer(int indent) { char spaces[256]; @@ -714,15 +834,26 @@ void LayerAndroid::showLayer(int indent) for (int i = 0; i < indent; i++) spaces[i] = ' '; - if (!indent) + if (!indent) { XLOGC("\n\n--- LAYERS TREE ---"); + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + XLOGC("documentViewport(%d, %d, %d, %d)", + documentViewport.x(), documentViewport.y(), + documentViewport.width(), documentViewport.height()); + } IntRect r(0, 0, getWidth(), getHeight()); IntRect tr = m_drawTransform.mapRect(r); - XLOGC("%s [%d:0x%x] - %s - (%d, %d, %d, %d) %s prepareContext(%d), pic w: %d h: %d", + IntRect visible = visibleArea(); + IntRect clip(m_clippingRect.x(), m_clippingRect.y(), + m_clippingRect.width(), m_clippingRect.height()); + XLOGC("%s [%d:0x%x] - %s - area (%d, %d, %d, %d) - visible (%d, %d, %d, %d) " + "clip (%d, %d, %d, %d) %s prepareContext(%d), pic w: %d h: %d", spaces, uniqueId(), m_owningLayer, needsTexture() ? "needs a texture" : "no texture", tr.x(), tr.y(), tr.width(), tr.height(), + visible.x(), visible.y(), visible.width(), visible.height(), + clip.x(), clip.y(), clip.width(), clip.height(), contentIsScrollable() ? "SCROLLABLE" : "", prepareContext(), m_recordingPicture ? m_recordingPicture->width() : -1, @@ -855,6 +986,15 @@ void LayerAndroid::clearDirtyRegion() m_dirtyRegion.setEmpty(); } +void LayerAndroid::setState(GLWebViewState* state) +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->setState(state); + + m_state = state; +} + void LayerAndroid::prepare(GLWebViewState* glWebViewState) { m_state = glWebViewState; @@ -880,9 +1020,80 @@ void LayerAndroid::prepare(GLWebViewState* glWebViewState) m_imageTexture->prepareGL(); } +IntRect LayerAndroid::unclippedArea() +{ + IntRect area; + area.setX(0); + area.setY(0); + area.setWidth(getSize().width()); + area.setHeight(getSize().height()); + return area; +} + +IntRect LayerAndroid::visibleArea() +{ + IntRect area = unclippedArea(); + // First, we get the transformed area of the layer, + // in document coordinates + IntRect rect = m_drawTransform.mapRect(area); + int dx = rect.x(); + int dy = rect.y(); + + // Then we apply the clipping + IntRect clip(m_clippingRect); + rect.intersect(clip); + + // Now clip with the viewport in documents coordinate + IntRect documentViewport(TilesManager::instance()->shader()->documentViewport()); + rect.intersect(documentViewport); + + // Finally, let's return the visible area, in layers coordinate + rect.move(-dx, -dy); + return rect; +} + +bool LayerAndroid::drawCanvas(SkCanvas* canvas) +{ + if (!m_visible) + return false; + + bool askScreenUpdate = false; + + { + SkAutoCanvasRestore acr(canvas, true); + SkRect r; + r.set(m_clippingRect.x(), m_clippingRect.y(), + m_clippingRect.x() + m_clippingRect.width(), + m_clippingRect.y() + m_clippingRect.height()); + canvas->clipRect(r); + SkMatrix matrix; + GLUtils::toSkMatrix(matrix, m_drawTransform); + SkMatrix canvasMatrix = canvas->getTotalMatrix(); + matrix.postConcat(canvasMatrix); + canvas->setMatrix(matrix); + SkRect layerRect; + layerRect.fLeft = 0; + layerRect.fTop = 0; + layerRect.fRight = getWidth(); + layerRect.fBottom = getHeight(); + onDraw(canvas, m_drawOpacity); + } + + // When the layer is dirty, the UI thread should be notified to redraw. + askScreenUpdate |= drawChildrenCanvas(canvas); + m_atomicSync.lock(); + askScreenUpdate |= m_dirty; + if (askScreenUpdate || m_hasRunningAnimations || m_drawTransform.hasPerspective()) + addDirtyArea(m_state); + + m_atomicSync.unlock(); + return askScreenUpdate; +} + bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) { - TilesManager::instance()->shader()->clip(m_clippingRect); + FloatRect clippingRect = TilesManager::instance()->shader()->rectInScreenCoord(m_clippingRect); + TilesManager::instance()->shader()->clip(clippingRect); if (!m_visible) return false; @@ -905,6 +1116,26 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) return askScreenUpdate; } +bool LayerAndroid::drawChildrenCanvas(SkCanvas* canvas) +{ + bool askScreenUpdate = false; + int count = this->countChildren(); + if (count > 0) { + Vector <LayerAndroid*> sublayers; + for (int i = 0; i < count; i++) + sublayers.append(this->getChild(i)); + + // now we sort for the transparency + std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) { + LayerAndroid* layer = sublayers[i]; + askScreenUpdate |= layer->drawCanvas(canvas); + } + } + + return askScreenUpdate; +} + bool LayerAndroid::drawChildrenGL(GLWebViewState* glWebViewState, SkMatrix& matrix) { bool askScreenUpdate = false; diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index 15a581e..b536b22 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -99,9 +99,25 @@ class RenderLayer; class TiledPage; class PaintedSurface; +class TexturesResult { +public: + TexturesResult() + : fixed(0) + , scrollable(0) + , clipped(0) + , full(0) + {} + + int fixed; + int scrollable; + int clipped; + int full; +}; + class LayerAndroid : public Layer { public: enum LayerType { UndefinedLayer, WebCoreLayer, UILayer, NavCacheLayer }; + LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); LayerAndroid(SkPicture*); @@ -121,6 +137,9 @@ public: IntRect clippedRect() const; bool outsideViewport(); + IntRect unclippedArea(); + IntRect visibleArea(); + virtual bool needsTexture(); void removeTexture(PaintedSurface*); @@ -129,11 +148,17 @@ public: int nbTexturedLayers(); void showLayer(int indent); + void computeTexturesAmount(TexturesResult*); + float getScale() { return m_scale; } + void setState(GLWebViewState*); + // draw layer and its children via Z, pre-order traversal virtual bool drawGL(GLWebViewState*, SkMatrix&); bool drawChildrenGL(GLWebViewState*, SkMatrix&); + virtual bool drawCanvas(SkCanvas*); + bool drawChildrenCanvas(SkCanvas*); // prepare layer and its children via reverse-Z, post-order traversal void prepare(GLWebViewState*); @@ -212,7 +237,7 @@ public: This call is recursive, so it should be called on the root of the hierarchy. */ - void updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0); + bool updateFixedLayersPositions(SkRect viewPort, LayerAndroid* parentIframeLayer = 0); /** Call this to update the position attribute, so that later calls like bounds() will report the corrected position. @@ -284,6 +309,9 @@ public: ImageTexture* imageTexture() { return m_imageTexture; } int type() { return m_type; } + bool hasText() { return m_hasText; } + void checkTextPresence(); + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); @@ -387,8 +415,11 @@ private: RenderLayer* m_owningLayer; - GLWebViewState* m_state; int m_type; + GLWebViewState* m_state; + + bool m_hasText; + typedef Layer INHERITED; }; diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp index c0597a9..939d106 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp @@ -142,24 +142,17 @@ void PaintedSurface::prepare(GLWebViewState* state) m_layer->uniqueId(), m_layer, m_layer->getScale()); - int w = m_layer->getSize().width(); - int h = m_layer->getSize().height(); - - if (w != m_area.width()) - m_area.setWidth(w); - - if (h != m_area.height()) - m_area.setHeight(h); - - computeVisibleArea(); + IntRect visibleArea = computeVisibleArea(m_layer); m_scale = state->scale(); - XLOG("%x layer %d %x prepared at size (%d, %d) @ scale %.2f", this, m_layer->uniqueId(), - m_layer, w, h, m_scale); + // If we do not have text, we may as well limit ourselves to + // a scale factor of one... this saves up textures. + if (m_scale > 1 && !m_layer->hasText()) + m_scale = 1; m_tiledTexture->prepare(state, m_scale, m_pictureUsed != m_layer->pictureUsed(), - startFastSwap, m_visibleArea); + startFastSwap, visibleArea); } bool PaintedSurface::draw() @@ -192,20 +185,53 @@ const TransformationMatrix* PaintedSurface::transform() { return m_layer->drawTransform(); } -void PaintedSurface::computeVisibleArea() { +void PaintedSurface::computeTexturesAmount(TexturesResult* result) +{ + if (!m_tiledTexture) + return; + if (!m_layer) return; - IntRect layerRect = (*m_layer->drawTransform()).mapRect(m_area); - IntRect clippedRect = TilesManager::instance()->shader()->clippedRectWithViewport(layerRect); - m_visibleArea = (*m_layer->drawTransform()).inverse().mapRect(clippedRect); - if (!m_visibleArea.isEmpty()) { - float tileWidth = TilesManager::instance()->layerTileWidth(); - float tileHeight = TilesManager::instance()->layerTileHeight(); - int w = ceilf(m_area.width() * m_scale / tileWidth); - int h = ceilf(m_area.height() * m_scale / tileHeight); - if (w * h < MAX_UNCLIPPED_AREA) - m_visibleArea = m_area; - } + + IntRect unclippedArea = m_layer->unclippedArea(); + IntRect clippedVisibleArea = m_layer->visibleArea(); + // get two numbers here: + // - textures needed for a clipped area + // - textures needed for an un-clipped area + int nbTexturesUnclipped = m_tiledTexture->nbTextures(unclippedArea, m_scale); + int nbTexturesClipped = m_tiledTexture->nbTextures(clippedVisibleArea, m_scale); + + // Set kFixedLayers level + if (m_layer->isFixed()) + result->fixed += nbTexturesClipped; + + // Set kScrollableAndFixedLayers level + if (m_layer->contentIsScrollable() + || m_layer->isFixed()) + result->scrollable += nbTexturesClipped; + + // Set kClippedTextures level + result->clipped += nbTexturesClipped; + + // Set kAllTextures level + if (m_layer->contentIsScrollable()) + result->full += nbTexturesClipped; + else + result->full += nbTexturesUnclipped; +} + +IntRect PaintedSurface::computeVisibleArea(LayerAndroid* layer) { + IntRect area; + if (!layer) + return area; + + if (!layer->contentIsScrollable() + && layer->state()->layersRenderingMode() == GLWebViewState::kAllTextures) + area = layer->unclippedArea(); + else + area = layer->visibleArea(); + + return area; } bool PaintedSurface::owns(BaseTileTexture* texture) diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h index 2e01b80..83b2c9b 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.h +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h @@ -63,14 +63,13 @@ public: bool owns(BaseTileTexture* texture); - void computeVisibleArea(); + void computeTexturesAmount(TexturesResult*); + IntRect computeVisibleArea(LayerAndroid*); // TilePainter methods for TiledTexture virtual const TransformationMatrix* transform(); // used by TiledTexture - const IntRect& area() { return m_area; } - const IntRect& visibleArea() { return m_visibleArea; } float scale() { return m_scale; } float opacity(); unsigned int pictureUsed() { return m_pictureUsed; } @@ -81,8 +80,6 @@ private: LayerAndroid* m_layer; DualTiledTexture* m_tiledTexture; - IntRect m_area; - IntRect m_visibleArea; float m_scale; unsigned int m_pictureUsed; diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp index 20d1299..241cbef 100644 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp +++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.cpp @@ -27,6 +27,11 @@ #include <wtf/text/CString.h> +#include <wtf/CurrentTime.h> +#include <cutils/log.h> +#include <wtf/text/CString.h> +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PerformanceMonitor", __VA_ARGS__) + namespace WebCore { PerformanceMonitor::PerformanceMonitor() @@ -78,4 +83,22 @@ float PerformanceMonitor::getAverageDuration(const String &tag) return m_tags.get(tag)->average_ms; } +void PerformanceMonitor::display(int limit) +{ + bool shown = false; + HashMap<String, PerfItem*, StringHash>::iterator end = m_tags.end(); + for (HashMap<String, PerfItem*, StringHash>::iterator it = m_tags.begin(); it != end; ++it) { + PerfItem* item = it->second; + if (item->average_ms > limit) { + if (!shown) { + XLOGC("=== DISPLAY MONITOR ===="); + shown = true; + } + XLOGC("item %s took longer than %d ms: %.2f", it->first.latin1().data(), limit, item->average_ms); + } + } + if (shown) + XLOGC("=== END DISPLAY MONITOR ===="); +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h index f4aaa92..4ebbf6a 100644 --- a/Source/WebCore/platform/graphics/android/PerformanceMonitor.h +++ b/Source/WebCore/platform/graphics/android/PerformanceMonitor.h @@ -48,6 +48,7 @@ public: void start(const String &tag); void stop(const String &tag); float getAverageDuration(const String &tag); + void display(int limit); private: HashMap<String, PerfItem*, StringHash> m_tags; diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index f66c7c1..8bf6fcc 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -70,6 +70,10 @@ RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) #ifdef DEBUG_COUNT ClassTracker::instance()->increment("RasterRenderer"); #endif + m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, + TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + m_bitmap.allocPixels(); } RasterRenderer::~RasterRenderer() @@ -84,20 +88,15 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can if (renderInfo.measurePerf) m_perfMon.start(TAG_CREATE_BITMAP); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, - renderInfo.invalRect->width(), renderInfo.invalRect->height()); - bitmap.allocPixels(); if (renderInfo.baseTile->isLayerTile()) { - bitmap.setIsOpaque(false); - bitmap.eraseARGB(0, 0, 0, 0); + m_bitmap.setIsOpaque(false); + m_bitmap.eraseARGB(0, 0, 0, 0); } else { - bitmap.setIsOpaque(true); - bitmap.eraseARGB(255, 255, 255, 255); + m_bitmap.setIsOpaque(true); + m_bitmap.eraseARGB(255, 255, 255, 255); } - SkDevice* device = new SkDevice(NULL, bitmap, false); + SkDevice* device = new SkDevice(NULL, m_bitmap, false); if (renderInfo.measurePerf) { m_perfMon.stop(TAG_CREATE_BITMAP); diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h index 4308452..69dfaf8 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.h @@ -29,6 +29,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "BaseRenderer.h" +#include "SkBitmap.h" #include "SkRect.h" class SkCanvas; @@ -50,6 +51,9 @@ protected: virtual void renderingComplete(const TileRenderInfo& renderInfo, SkCanvas* canvas); virtual const String* getPerformanceTags(int& tagCount); +private: + SkBitmap m_bitmap; + }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp index bca2fd4..2643d2c 100644 --- a/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/ScrollableLayerAndroid.cpp @@ -1,6 +1,8 @@ #include "config.h" #include "ScrollableLayerAndroid.h" +#include "GLWebViewState.h" + #if USE(ACCELERATED_COMPOSITING) namespace WebCore { @@ -19,6 +21,10 @@ bool ScrollableLayerAndroid::scrollTo(int x, int y) return false; setPosition(m_scrollLimits.fLeft - newX, m_scrollLimits.fTop - newY); + + if (state()) + state()->scrolledLayer(this); + return true; } diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp index 0aad081..30b5c86 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -408,6 +408,8 @@ void ShaderProgram::setViewRect(const IntRect& viewRect) translate.scale3d(1, -1, 1); m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix; + + m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(viewRect); } // This function transform a clip rect extracted from the current layer @@ -437,6 +439,11 @@ FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect) return m_documentToScreenMatrix.mapRect(rect); } +FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect) +{ + return m_documentToScreenMatrix.inverse().mapRect(rect); +} + FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect) { FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect); diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h index dbacd57..b309872 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h @@ -67,6 +67,7 @@ public: FloatRect rectInInvScreenCoord(const FloatRect& rect); FloatRect rectInScreenCoord(const FloatRect& rect); + FloatRect convertScreenCoordToDocumentCoord(const FloatRect& rect); FloatRect convertInvScreenCoordToScreenCoord(const FloatRect& rect); FloatRect convertScreenCoordToInvScreenCoord(const FloatRect& rect); @@ -75,6 +76,7 @@ public: void setScreenClip(const IntRect& clip); void clip(const FloatRect& rect); IntRect clippedRectWithViewport(const IntRect& rect, int margin = 0); + FloatRect documentViewport() { return m_documentViewport; } void resetBlending(); float contrast() { return m_contrast; } @@ -125,6 +127,8 @@ private: int m_titleBarHeight; IntRect m_webViewRect; + FloatRect m_documentViewport; + // uniforms GLint m_hProjectionMatrix; GLint m_hAlpha; diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index c097c58..3c262d4 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -374,8 +374,8 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds) bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) { - // TODO: consider other flags so the pre-rendered tiles aren't so ugly - static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, 0); + static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags, + SkPaint::kAntiAlias_Flag); if (!m_glWebViewState) return false; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index 30aa022..e2c13a9 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -59,12 +59,13 @@ bool TiledTexture::ready() { bool tilesVisible = false; for (unsigned int i = 0; i < m_tiles.size(); i++) { BaseTile* tile = m_tiles[i]; - if (tile->isTileVisible(m_area) && !tile->isTileReady()) { - tilesAllReady = false; - break; - } - if (tile->isTileVisible(m_area)) + if (tile->isTileVisible(m_area)) { tilesVisible = true; + if (!tile->isTileReady()) { + tilesAllReady = false; + break; + } + } } // For now, if no textures are available, consider ourselves as ready // in order to unblock the zooming process. @@ -74,38 +75,47 @@ bool TiledTexture::ready() { || !tilesVisible || tilesAllReady; } -void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, - bool startFastSwap, IntRect& visibleArea) +IntRect TiledTexture::computeTilesArea(IntRect& visibleArea, float scale) { - if (!m_surface) - return; - - if (!m_surface->layer()) - return; - - // first, how many tiles do we need + IntRect computedArea; IntRect area(visibleArea.x() * scale, visibleArea.y() * scale, ceilf(visibleArea.width() * scale), ceilf(visibleArea.height() * scale)); if (area.width() == 0 && area.height() == 0) { - m_area.setWidth(0); - m_area.setHeight(0); - return; + computedArea.setWidth(0); + computedArea.setHeight(0); + return computedArea; } int tileWidth = TilesManager::instance()->layerTileWidth(); int tileHeight = TilesManager::instance()->layerTileHeight(); - m_area.setX(area.x() / tileWidth); - m_area.setY(area.y() / tileHeight); + computedArea.setX(area.x() / tileWidth); + computedArea.setY(area.y() / tileHeight); float right = (area.x() + area.width()) / (float) tileWidth; float bottom = (area.y() + area.height()) / (float) tileHeight; - m_area.setWidth(ceilf(right) - m_area.x()); - m_area.setHeight(ceilf(bottom) - m_area.y()); + computedArea.setWidth(ceilf(right) - computedArea.x()); + computedArea.setHeight(ceilf(bottom) - computedArea.y()); + return computedArea; +} - XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", +void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint, + bool startFastSwap, IntRect& area) +{ + if (!m_surface) + return; + + if (!m_surface->layer()) + return; + + m_area = computeTilesArea(area, scale); + if (m_area.isEmpty()) + return; + + XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of " + " %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles", this, scale, visibleArea.x(), visibleArea.y(), visibleArea.width(), visibleArea.height(), @@ -210,6 +220,12 @@ BaseTile* TiledTexture::getTile(int x, int y) return 0; } +int TiledTexture::nbTextures(IntRect& area, float scale) +{ + IntRect computedTilesArea = computeTilesArea(area, scale); + return computedTilesArea.width() * computedTilesArea.height(); +} + bool TiledTexture::draw() { #ifdef DEBUG diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index c6e9e09..5a47cd9 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.h +++ b/Source/WebCore/platform/graphics/android/TiledTexture.h @@ -65,6 +65,8 @@ public: removeTiles(); }; + IntRect computeTilesArea(IntRect& visibleArea, float scale); + void prepare(GLWebViewState* state, float scale, bool repaint, bool startFastSwap, IntRect& visibleArea); bool draw(); @@ -87,6 +89,8 @@ public: PaintedSurface* surface() { return m_surface; } + int nbTextures(IntRect& area, float scale); + private: bool tileIsVisible(BaseTile* tile); @@ -117,6 +121,15 @@ public: bool draw(); void update(const SkRegion& dirtyArea, SkPicture* picture); bool owns(BaseTileTexture* texture); + + int nbTextures(IntRect& area, float scale) + { + // TODO: consider the zooming case for the backTexture + if (!m_frontTexture) + return 0; + return m_frontTexture->nbTextures(area, scale); + } + private: // Delay before we schedule a new tile at the new scale factor static const double s_zoomUpdateDelay = 0.2; // 200 ms diff --git a/Source/WebKit/android/RenderSkinCombo.cpp b/Source/WebKit/android/RenderSkinCombo.cpp index 970e093..1711cfa 100644 --- a/Source/WebKit/android/RenderSkinCombo.cpp +++ b/Source/WebKit/android/RenderSkinCombo.cpp @@ -58,14 +58,14 @@ enum BorderStyle { // width on all sides, except on the right when it's significantly // wider to allow for the arrow. const int RenderSkinCombo::arrowMargin[ResolutionCount] = { - 22, // Medium resolution - 34, // High resolution - 46 // Extra high resolution + 16, // Medium resolution + 25, // High resolution + 34 // Extra high resolution }; const int RenderSkinCombo::padMargin[ResolutionCount] = { - 2, // Medium resolution - 5, // High resolution - 6 // Extra high resolution + 1, // Medium resolution + 1, // High resolution + 1 // Extra high resolution }; namespace { @@ -76,15 +76,15 @@ namespace { // right hand border width happens to be the same as arrowMargin // defined above. const int stretchMargin[RenderSkinAndroid::ResolutionCount] = { // border width for the bottom and left of the 9-patch - 3, // Medium resolution - 5, // High resolution - 6 // Extra high resolution + 2, // Medium resolution + 2, // High resolution + 3 // Extra high resolution }; const int stretchTop[RenderSkinAndroid::ResolutionCount] = { // border width for the top of the 9-patch - 15, // Medium resolution + 16, // Medium resolution 23, // High resolution - 34 // Extra high resolution + 32 // Extra high resolution }; // Finally, if the border is defined by the CSS, we only draw the @@ -95,9 +95,16 @@ const int stretchTop[RenderSkinAndroid::ResolutionCount] = { // border width for // image is the same as stretchMargin above, but we need to know the width // of the arrow. const int arrowWidth[RenderSkinAndroid::ResolutionCount] = { - 22, // Medium resolution - 31, // High resolution - 42 // Extra high resolution + 18, // Medium resolution + 27, // High resolution + 36 // Extra high resolution +}; + +// scale factors for various resolutions +const float scaleFactor[RenderSkinAndroid::ResolutionCount] = { + 1.0f, // medium res + 1.5f, // high res + 2.0f // extra high res }; // Store the calculated 9 patch margins for each border style. @@ -109,6 +116,11 @@ bool isDecoded = false; // True if all assets were decoded } // namespace +int RenderSkinCombo::minHeight() { + return SkScalarRound(stretchTop[RenderSkinAndroid::DrawableResolution()] + / scaleFactor[RenderSkinAndroid::DrawableResolution()]); +} + void RenderSkinCombo::Decode() { if (isDecodingAttempted) @@ -135,9 +147,9 @@ void RenderSkinCombo::Decode() // Calculate 9 patch margins. SkIRect fullAssetMargin; fullAssetMargin.fLeft = stretchMargin[res]; - fullAssetMargin.fTop = stretchTop[res]; + fullAssetMargin.fTop = stretchMargin[res]; fullAssetMargin.fRight = arrowMargin[res] + stretchMargin[res]; - fullAssetMargin.fBottom = stretchMargin[res]; + fullAssetMargin.fBottom = stretchTop[res]; SkIRect noBorderMargin; noBorderMargin.fLeft = 0; @@ -157,8 +169,9 @@ bool RenderSkinCombo::Draw(SkCanvas* canvas, Node* element, int x, int y, int wi if (!isDecoded) return true; + int resolution = RenderSkinAndroid::DrawableResolution(); State state = (element->isElementNode() && static_cast<Element*>(element)->isEnabledFormControl()) ? kNormal : kDisabled; - height = std::max(height, (stretchMargin[RenderSkinAndroid::DrawableResolution()]<<1) + 1); + height = std::max(height, (stretchMargin[resolution] * 2)); SkRect bounds; BorderStyle drawBorder = FullAsset; @@ -185,7 +198,15 @@ bool RenderSkinCombo::Draw(SkCanvas* canvas, Node* element, int x, int y, int wi bounds.fBottom -= SkIntToScalar(style->borderBottomWidth()); drawBorder = NoBorder; } + float scale = scaleFactor[resolution]; + bounds.fLeft = bounds.fLeft * scale; + bounds.fRight = bounds.fRight * scale; + bounds.fTop = bounds.fTop * scale; + bounds.fBottom = bounds.fBottom * scale; + int count = canvas->save(); + canvas->scale(1.0f / scale, 1.0f / scale); SkNinePatch::DrawNine(canvas, bounds, bitmaps[state][drawBorder], margin[drawBorder]); + canvas->restoreToCount(count); return false; } diff --git a/Source/WebKit/android/RenderSkinCombo.h b/Source/WebKit/android/RenderSkinCombo.h index 4814199..a11faac 100644 --- a/Source/WebKit/android/RenderSkinCombo.h +++ b/Source/WebKit/android/RenderSkinCombo.h @@ -48,6 +48,7 @@ public: // The image is wider than the RenderObject, so this accounts for that. static int extraWidth() { return arrowMargin[RenderSkinAndroid::DrawableResolution()]; } + static int minHeight(); static int padding() { return padMargin[RenderSkinAndroid::DrawableResolution()]; } diff --git a/Source/WebKit/android/WebCoreSupport/ChromiumInit.cpp b/Source/WebKit/android/WebCoreSupport/ChromiumInit.cpp index f5029d5..500975c 100644 --- a/Source/WebKit/android/WebCoreSupport/ChromiumInit.cpp +++ b/Source/WebKit/android/WebCoreSupport/ChromiumInit.cpp @@ -68,8 +68,7 @@ void initChromium() if (!initCalled) { logging::SetLogMessageHandler(logMessageHandler); networkChangeNotifier.reset(net::NetworkChangeNotifier::Create()); - // Disable SPDY for bug 5226268 [Browser] http keep-alive packets are sent too frequently to network - // net::HttpNetworkLayer::EnableSpdy("npn"); + net::HttpNetworkLayer::EnableSpdy("npn"); initCalled = true; jni::SetJavaVM(JSC::Bindings::getJavaVM()); } diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index d4d2cc7..ed2a326 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -2127,7 +2127,8 @@ static jboolean GetShouldStartScrolledRight(JNIEnv *env, jobject obj, RenderStyle* style = document->renderer()->style(); WritingMode writingMode = style->writingMode(); LOG_ASSERT(writingMode != WebCore::BottomToTopWritingMode, - "BottomToTopWritingMode isn't supported"); + "BottomToTopWritingMode isn't possible in any " + "language and cannot be specified in w3c writing-mode."); if (writingMode == WebCore::RightToLeftWritingMode) startScrolledRight = true; // vertical-rl pages start scrolled right else if (writingMode == WebCore::TopToBottomWritingMode) diff --git a/Source/WebKit/android/nav/CacheBuilder.cpp b/Source/WebKit/android/nav/CacheBuilder.cpp index 623d2cb..0c9e85c 100644 --- a/Source/WebKit/android/nav/CacheBuilder.cpp +++ b/Source/WebKit/android/nav/CacheBuilder.cpp @@ -2882,8 +2882,6 @@ bool CacheBuilder::setData(CachedFrame* cachedFrame) RenderLayer* layer = renderer->enclosingLayer(); if (layer == NULL) return false; - if (layer->width() == 0 || layer->height() == 0) - return false; if (!frame->view()) return false; int x, y; diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 60bdd3e..59fd6da 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -204,6 +204,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir) m_ringAnimationEnd = 0; m_baseLayer = 0; m_glDrawFunctor = 0; + m_isDrawingPaused = false; m_buttonSkin = drawableDir.isEmpty() ? 0 : new RenderSkinButton(drawableDir); #if USE(ACCELERATED_COMPOSITING) m_glWebViewState = 0; @@ -542,7 +543,7 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, WebCore::In } } if (ret || m_glWebViewState->currentPictureCounter() != pic) - return true; + return !m_isDrawingPaused; #endif return false; } @@ -1544,6 +1545,7 @@ BaseLayerAndroid* getBaseLayer() { return m_baseLayer; } + bool m_isDrawingPaused; private: // local state for WebView // private to getFrameCache(); other functions operate in a different thread CachedRoot* m_frameCacheUI; // navigation data ready for use @@ -2044,8 +2046,8 @@ static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj) : WebCore::IntRect(0, 0, 0, 0); // Inset the rect by 1 unit, so that the focus candidate's border can still // be seen behind it. - return createJavaRect(env, bounds.x() + 1, bounds.y() + 1, - bounds.maxX() - 1, bounds.maxY() - 1); + return createJavaRect(env, bounds.x(), bounds.y(), + bounds.maxX(), bounds.maxY()); } static jobject nativeFocusCandidatePaddingRect(JNIEnv *env, jobject obj) @@ -2703,6 +2705,12 @@ static int nativeGetBackgroundColor(JNIEnv* env, jobject obj) return SK_ColorWHITE; } +static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView, + jboolean pause) +{ + ((WebView*)nativeView)->m_isDrawingPaused = pause; +} + /* * JNI registration */ @@ -2915,6 +2923,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeGetProperty }, { "nativeOnTrimMemory", "(I)V", (void*) nativeOnTrimMemory }, + { "nativeSetPauseDrawing", "(IZ)V", + (void*) nativeSetPauseDrawing }, }; int registerWebView(JNIEnv* env) |