From 176a19c613e0c025ecd5f82730a24c0ff128edef Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Wed, 21 Sep 2011 11:32:15 -0700 Subject: Prefetch browser content with tiled page bug:5262519 Use the tiled page not used by content rendering to render much fewer tiles for the same content, at an inflated scale. These prefetched tiles are prioritized for painting above all others, so that content is (almost) always visible on the base layer. Change-Id: I598b7925cb68beef632f828df3ae522a0b21e2b4 --- .../platform/graphics/android/BaseLayerAndroid.cpp | 56 ++++++++++++++++++++++ .../platform/graphics/android/BaseLayerAndroid.h | 2 + .../graphics/android/PaintTileOperation.cpp | 4 ++ .../platform/graphics/android/TiledPage.cpp | 9 ++++ .../WebCore/platform/graphics/android/TiledPage.h | 3 ++ 5 files changed, 74 insertions(+) (limited to 'Source') diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 0ab28d7..1aefd86 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -54,6 +54,12 @@ #endif // DEBUG +// TODO: dynamically determine based on DPI +#define PREFETCH_SCALE_MODIFIER 0.3 +#define PREFETCH_OPACITY 1 +#define PREFETCH_X_DIST 1 +#define PREFETCH_Y_DIST 2 + namespace WebCore { using namespace android; @@ -116,6 +122,49 @@ void BaseLayerAndroid::drawCanvas(SkCanvas* canvas) } #if USE(ACCELERATED_COMPOSITING) + +void BaseLayerAndroid::prefetchBasePicture(SkRect& viewport, float currentScale, + TiledPage* prefetchTiledPage) +{ + SkIRect bounds; + float prefetchScale = currentScale * PREFETCH_SCALE_MODIFIER; + + float invTileWidth = (prefetchScale) + / TilesManager::instance()->tileWidth(); + float invTileHeight = (prefetchScale) + / TilesManager::instance()->tileHeight(); + bool goingDown = m_glWebViewState->goingDown(); + bool goingLeft = m_glWebViewState->goingLeft(); + + + XLOG("fetch rect %f %f %f %f, scale %f", + viewport.fLeft, + viewport.fTop, + viewport.fRight, + viewport.fBottom, + scale); + + bounds.fLeft = static_cast(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST; + bounds.fTop = static_cast(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST; + bounds.fRight = static_cast(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST; + bounds.fBottom = static_cast(ceilf(viewport.fBottom * invTileHeight)) + PREFETCH_Y_DIST; + + XLOG("prefetch rect %d %d %d %d, scale %f, preparing page %p", + bounds.fLeft, bounds.fTop, + bounds.fRight, bounds.fBottom, + scale * PREFETCH_SCALE, + prefetchTiledPage); + + prefetchTiledPage->setScale(prefetchScale); + prefetchTiledPage->updateTileDirtiness(bounds); + prefetchTiledPage->prepare(goingDown, goingLeft, bounds, + TiledPage::ExpandedBounds); + prefetchTiledPage->swapBuffersIfReady(bounds, + prefetchScale, + TiledPage::SwapWhateverIsReady); + prefetchTiledPage->draw(PREFETCH_OPACITY, bounds); +} + bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double currentTime, bool* buffersSwappedPtr) { @@ -183,6 +232,13 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, bool scrolling = m_scrollState != NotScrolling; bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState(); + // prefetch in the nextTiledPage if unused by zooming (even if not scrolling + // since we want the tiles to be ready before they're needed) + bool usePrefetchPage = !zooming; + nextTiledPage->setIsPrefetchPage(usePrefetchPage); + if (usePrefetchPage) + prefetchBasePicture(viewport, scale, nextTiledPage); + // When we aren't zooming, we should TRY and swap tile buffers if they're // ready. When scrolling, we swap whatever's ready. Otherwise, buffer until // the entire page is ready and then swap. diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h index a42a372..26fd158 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.h @@ -66,6 +66,8 @@ public: void swapExtra(BaseLayerAndroid* base) { m_extra.swap(base->m_extra); } private: #if USE(ACCELERATED_COMPOSITING) + void prefetchBasePicture(SkRect& viewport, float currentScale, + TiledPage* prefetchTiledPage); bool drawBasePictureInGL(SkRect& viewport, float scale, double currentTime, bool* buffersSwappedPtr); diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp index aa3f320..19b49f1 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp @@ -81,6 +81,10 @@ int PaintTileOperation::priority() unsigned long long drawDelta = currentDraw - m_tile->drawCount(); int priority = 100000 * (int)std::min(drawDelta, (unsigned long long)1000); + // prioritize the prefetch page, if it exists + if (!m_tile->page() || !m_tile->page()->isPrefetchPage()) + priority += 200000; + // prioritize unpainted tiles, within the same drawCount if (m_tile->frontTexture()) priority += 50000; diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index ede7d1b..2b8ebcc 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -31,6 +31,8 @@ #include "GLUtils.h" #include "IntRect.h" #include "PaintTileOperation.h" +#include "SkPaint.h" +#include "SkPaintFlagsDrawFilter.h" #include "TilesManager.h" #include @@ -65,6 +67,7 @@ TiledPage::TiledPage(int id, GLWebViewState* state) , m_glWebViewState(state) , m_latestPictureInval(0) , m_prepare(false) + , m_isPrefetchPage(false) { m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; #ifdef DEBUG_COUNT @@ -366,9 +369,15 @@ 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); + if (!m_glWebViewState) return false; + if (isPrefetchPage()) + canvas->setDrawFilter(&prefetchFilter); + *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas); return true; } diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index 946421c..c903abc 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -98,6 +98,8 @@ public: void updateBaseTileSize(); bool scrollingDown() { return m_scrollingDown; } SkIRect* expandedTileBounds() { return &m_expandedTileBounds; } + bool isPrefetchPage() { return m_isPrefetchPage; } + void setIsPrefetchPage(bool isPrefetch) { m_isPrefetchPage = isPrefetch; } private: void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds); @@ -127,6 +129,7 @@ private: bool m_prepare; bool m_scrollingDown; SkIRect m_expandedTileBounds; + bool m_isPrefetchPage; }; } // namespace WebCore -- cgit v1.1