OSDN Git Service

Don't prepare offscreen tiles
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / TiledPage.cpp
index e596380..2b3c2ee 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,8 @@ TiledPage::TiledPage(int id, GLWebViewState* state)
     , m_glWebViewState(state)
     , m_latestPictureInval(0)
     , m_prepare(false)
+    , m_isPrefetchPage(false)
+    , m_willDraw(false)
 {
     m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1];
 #ifdef DEBUG_COUNT
@@ -139,9 +143,6 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC
 
 void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds)
 {
-    if (y < 0)
-        return;
-
     for (int i = 0; i < tilesInRow; i++) {
         int x = firstTileX;
 
@@ -153,9 +154,6 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y
         else
             x += i;
 
-        if (x < 0)
-            continue;
-
         BaseTile* currentTile = 0;
         BaseTile* availableTile = 0;
         for (int j = 0; j < m_baseTileSize; j++) {
@@ -244,9 +242,6 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
     int nbTilesWidth = tileBounds.width();
     int nbTilesHeight = tileBounds.height();
 
-    int lastTileX = tileBounds.fRight - 1;
-    int lastTileY = tileBounds.fBottom - 1;
-
     // Expand number of tiles to allow tiles outside of viewport to be prepared for
     // smoother scrolling.
     int nTilesToPrepare = nbTilesWidth * nbTilesHeight;
@@ -258,18 +253,27 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
         int expandY = m_glWebViewState->expandedTileBoundsY();
 
         firstTileX -= expandX;
-        lastTileX += expandX;
         nbTilesWidth += expandX * 2;
 
         firstTileY -= expandY;
-        lastTileY += expandY;
         nbTilesHeight += expandY * 2;
     }
 
-    m_expandedTileBounds.fLeft = firstTileX;
-    m_expandedTileBounds.fTop = firstTileY;
-    m_expandedTileBounds.fRight = lastTileX;
-    m_expandedTileBounds.fBottom = lastTileY;
+    // crop the prepared region to the contents of the base layer
+    float maxWidthTiles = m_glWebViewState->baseContentWidth() * m_scale / TilesManager::tileWidth();
+    float maxHeightTiles = m_glWebViewState->baseContentHeight() * m_scale / TilesManager::tileHeight();
+
+    // adjust perimeter to not go outside base content bounds
+    if (firstTileX < 0) {
+        nbTilesWidth += firstTileX;
+        firstTileX = 0;
+    }
+    if (firstTileY < 0) {
+        nbTilesHeight += firstTileY;
+        firstTileY = 0;
+    }
+    nbTilesWidth = std::min(nbTilesWidth, static_cast<int>(ceilf(maxWidthTiles)) - firstTileX);
+    nbTilesHeight = std::min(nbTilesHeight, static_cast<int>(ceilf(maxHeightTiles)) - firstTileY);
 
     // check against corrupted scale values giving bad height/width (use float to avoid overflow)
     float numTiles = static_cast<float>(nbTilesHeight) * static_cast<float>(nbTilesWidth);
@@ -285,7 +289,35 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound
     m_prepare = true;
 }
 
-bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapMethod swap)
+bool TiledPage::hasMissingContent(const SkIRect& tileBounds)
+{
+    int neededTiles = tileBounds.width() * tileBounds.height();
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tileBounds.contains(tile.x(), tile.y())) {
+            if (tile.frontTexture())
+                neededTiles--;
+        }
+    }
+    return neededTiles > 0;
+}
+
+bool TiledPage::isReady(const SkIRect& tileBounds)
+{
+    int neededTiles = tileBounds.width() * tileBounds.height();
+    XLOG("tiled page %p needs %d ready tiles", this, neededTiles);
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tileBounds.contains(tile.x(), tile.y())) {
+            if (tile.isTileReady())
+                neededTiles--;
+        }
+    }
+    XLOG("tiled page %p still needs %d ready tiles", this, neededTiles);
+    return neededTiles == 0;
+}
+
+bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale)
 {
     if (!m_glWebViewState)
         return false;
@@ -297,62 +329,44 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale, SwapM
         return false;
 
     int swaps = 0;
-    if (swap == SwapWholePage) {
-        for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
-            for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
-                BaseTile* t = getBaseTile(x, y);
-                if (!t || !t->isTileReady())
-                    return false;
-            }
-        }
-        for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
-            for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
-                BaseTile* t = getBaseTile(x, y);
-                if (t->swapTexturesIfNeeded())
-                    swaps++;
-            }
-        }
-        XLOG("%p whole page swapped %d textures, returning true", this, swaps);
-        return true;
-    } else { // SwapWhateveryIsReady
-        bool fullSwap = true;
-        for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
-            for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
-                BaseTile* t = getBaseTile(x, y);
-                if (!t || !t->isTileReady())
-                    fullSwap = false;
-                else {
-                    if (t->swapTexturesIfNeeded())
-                        swaps++;
-                }
-            }
+    bool fullSwap = true;
+    for (int x = tileBounds.fLeft; x < tileBounds.fRight; x++) {
+        for (int y = tileBounds.fTop; y < tileBounds.fBottom; y++) {
+            BaseTile* t = getBaseTile(x, y);
+            if (!t || !t->isTileReady())
+                fullSwap = false;
         }
-        XLOG("%p greedy swap swapped %d tiles, returning %d", this, swaps, fullSwap);
-        return fullSwap;
     }
+
+    // swap every tile on page (even if off screen)
+    for (int j = 0; j < m_baseTileSize; j++) {
+        BaseTile& tile = m_baseTiles[j];
+        if (tile.swapTexturesIfNeeded())
+            swaps++;
+    }
+
+    XLOG("%p greedy swapped %d textures, returning true", this, swaps);
+    return fullSwap;
 }
 
+void TiledPage::prepareForDrawGL(float transparency, const SkIRect& tileBounds)
+{
+    m_willDraw = true;
+    m_transparency = transparency;
+    m_tileBounds = tileBounds;
+}
 
-void TiledPage::draw(float transparency, const SkIRect& tileBounds)
+void TiledPage::drawGL()
 {
-    if (!m_glWebViewState)
+    if (!m_glWebViewState || m_transparency == 0 || !m_willDraw)
         return;
 
     const float tileWidth = TilesManager::tileWidth() * m_invScale;
     const float tileHeight = TilesManager::tileHeight() * m_invScale;
 
-    SkIRect actualTileBounds = tileBounds;
-    actualTileBounds.fTop -= m_glWebViewState->expandedTileBoundsY();
-    actualTileBounds.fBottom += m_glWebViewState->expandedTileBoundsY();
-    actualTileBounds.fLeft -= m_glWebViewState->expandedTileBoundsX();
-    actualTileBounds.fRight += m_glWebViewState->expandedTileBoundsX();
-
-    actualTileBounds.fTop = std::max(0, actualTileBounds.fTop);
-    actualTileBounds.fLeft = std::max(0, actualTileBounds.fLeft);
-
     for (int j = 0; j < m_baseTileSize; j++) {
         BaseTile& tile = m_baseTiles[j];
-        bool tileInView = actualTileBounds.contains(tile.x(), tile.y());
+        bool tileInView = m_tileBounds.contains(tile.x(), tile.y());
         if (tileInView) {
             SkRect rect;
             rect.fLeft = tile.x() * tileWidth;
@@ -360,26 +374,29 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds)
             rect.fRight = rect.fLeft + tileWidth;
             rect.fBottom = rect.fTop + tileHeight;
 
-            tile.draw(transparency, rect, m_scale);
+            tile.draw(m_transparency, rect, m_scale);
         }
 
         TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView);
     }
+    m_willDraw = false; // don't redraw until re-prepared
 }
 
 bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
 {
+    static SkPaintFlagsDrawFilter prefetchFilter(SkPaint::kAllFlags,
+                                                 SkPaint::kAntiAlias_Flag);
+
     if (!m_glWebViewState)
         return false;
 
+    if (isPrefetchPage())
+        canvas->setDrawFilter(&prefetchFilter);
+
     *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas);
     return true;
 }
 
-void TiledPage::paintExtra(SkCanvas* canvas)
-{
-}
-
 TiledPage* TiledPage::sibling()
 {
     if (!m_glWebViewState)