OSDN Git Service

Prefetch browser content with tiled page
authorChris Craik <ccraik@google.com>
Wed, 21 Sep 2011 18:32:15 +0000 (11:32 -0700)
committerChris Craik <ccraik@google.com>
Wed, 21 Sep 2011 22:46:36 +0000 (15:46 -0700)
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

Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
Source/WebCore/platform/graphics/android/BaseLayerAndroid.h
Source/WebCore/platform/graphics/android/PaintTileOperation.cpp
Source/WebCore/platform/graphics/android/TiledPage.cpp
Source/WebCore/platform/graphics/android/TiledPage.h

index 0ab28d7..1aefd86 100644 (file)
 
 #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<int>(floorf(viewport.fLeft * invTileWidth)) - PREFETCH_X_DIST;
+    bounds.fTop = static_cast<int>(floorf(viewport.fTop * invTileHeight)) - PREFETCH_Y_DIST;
+    bounds.fRight = static_cast<int>(ceilf(viewport.fRight * invTileWidth)) + PREFETCH_X_DIST;
+    bounds.fBottom = static_cast<int>(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.
index a42a372..26fd158 100644 (file)
@@ -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);
 
index aa3f320..19b49f1 100644 (file)
@@ -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;
index ede7d1b..2b8ebcc 100644 (file)
@@ -31,6 +31,8 @@
 #include "GLUtils.h"
 #include "IntRect.h"
 #include "PaintTileOperation.h"
+#include "SkPaint.h"
+#include "SkPaintFlagsDrawFilter.h"
 #include "TilesManager.h"
 
 #include <cutils/log.h>
@@ -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;
 }
index 946421c..c903abc 100644 (file)
@@ -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