diff options
| -rw-r--r-- | WebCore/platform/graphics/android/BaseLayerAndroid.cpp | 29 | ||||
| -rw-r--r-- | WebCore/platform/graphics/android/GLWebViewState.cpp | 33 | ||||
| -rw-r--r-- | WebCore/platform/graphics/android/GLWebViewState.h | 27 | ||||
| -rw-r--r-- | WebCore/platform/graphics/android/TiledPage.cpp | 107 | ||||
| -rw-r--r-- | WebCore/platform/graphics/android/TiledPage.h | 8 |
5 files changed, 113 insertions, 91 deletions
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index c7420c8..9e090a6 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -92,6 +92,7 @@ void BaseLayerAndroid::setContent(const PictureSet& src) android::Mutex::Autolock lock(m_drawLock); #endif m_content.set(src); + setSize(src.width(), src.height()); } void BaseLayerAndroid::drawCanvas(SkCanvas* canvas) @@ -117,14 +118,12 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) m_glWebViewState->setViewport(viewport, scale); - int firstTileX = m_glWebViewState->firstTileX(); - int firstTileY = m_glWebViewState->firstTileY(); + const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds(); + XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft, + viewportTileBounds.fTop, scale); - XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", firstTileX, firstTileY, scale); - if (scale == m_glWebViewState->currentScale()) { - m_glWebViewState->setOriginalTilesPosX(firstTileX); - m_glWebViewState->setOriginalTilesPosY(firstTileY); - } + if (scale == m_glWebViewState->currentScale()) + m_glWebViewState->setPreZoomBounds(viewportTileBounds); // If we have a different scale than the current one, we have to // decide what to do. The current behaviour is to delay an update, @@ -148,7 +147,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) // Check if the page is ready... if (m_glWebViewState->scaleRequestState() == GLWebViewState::kRequestNewScale - && nextTiledPage->ready(firstTileX, firstTileY)) { + && nextTiledPage->ready(viewportTileBounds)) { m_glWebViewState->setScaleRequestState(GLWebViewState::kReceivedNewScale); } @@ -162,8 +161,7 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) if (scale < m_glWebViewState->currentScale()) newTilesTransparency = 1 - transparency; - nextTiledPage->draw(newTilesTransparency, viewport, - firstTileX, firstTileY); + nextTiledPage->draw(newTilesTransparency, viewport, viewportTileBounds); // The transition between the two pages is finished, swap them if (currentTime > transitionTime) { @@ -173,21 +171,20 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale) } } else { // If the page is not ready, schedule it if needed. - nextTiledPage->prepare(goingDown, goingLeft, firstTileX, firstTileY); + nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds); } } // Display the current page TiledPage* tiledPage = m_glWebViewState->frontPage(); tiledPage->setScale(m_glWebViewState->currentScale()); - int originalTX = m_glWebViewState->originalTilesPosX(); - int originalTY = m_glWebViewState->originalTilesPosY(); - tiledPage->prepare(goingDown, goingLeft, originalTX, originalTY); - tiledPage->draw(transparency, viewport, originalTX, originalTY); + const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds(); + tiledPage->prepare(goingDown, goingLeft, preZoomBounds); + tiledPage->draw(transparency, viewport, preZoomBounds); bool ret = false; if (m_glWebViewState->scaleRequestState() != GLWebViewState::kNoScaleRequest - || !tiledPage->ready(originalTX, originalTY)) + || !tiledPage->ready(preZoomBounds)) ret = true; if (doSwap) diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp index 617690c..bcb5cbf 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -69,12 +69,6 @@ GLWebViewState::GLWebViewState() , m_futureScale(1) , m_updateTime(-1) , m_transitionTime(-1) - , m_originalTilesPosX(0) - , m_originalTilesPosY(0) - , m_nbTilesWidth(0) - , m_nbTilesHeight(0) - , m_firstTileX(0) - , m_firstTileY(0) , m_baseLayer(0) , m_currentPictureCounter(0) , m_usePageA(true) @@ -211,24 +205,35 @@ void GLWebViewState::swapPages() m_scaleRequestState = kNoScaleRequest; } +int GLWebViewState::baseContentWidth() +{ + return m_baseLayer ? m_baseLayer->getWidth() : 0; + +} +int GLWebViewState::baseContentHeight() +{ + return m_baseLayer ? m_baseLayer->getHeight() : 0; +} + void GLWebViewState::setViewport(SkRect& viewport, float scale) { if (m_viewport == viewport) return; m_viewport = viewport; - float fnbw = m_viewport.width() * scale / TilesManager::tileWidth(); - int nbw = static_cast<int>(ceilf(fnbw)); - float fnbh = m_viewport.height() * scale / TilesManager::tileHeight(); - int nbh = static_cast<int>(ceilf(fnbh)); - m_nbTilesWidth = nbw + 1; - m_nbTilesHeight = nbh + 1; XLOG("New VIEWPORT %.2f - %.2f %.2f - %.2f (w: %2.f h: %.2f scale: %.2f), nbw: %d nbh: %d", m_viewport.fLeft, m_viewport.fTop, m_viewport.fRight, m_viewport.fBottom, m_viewport.width(), m_viewport.height(), scale, m_nbTilesWidth, m_nbTilesHeight); - m_firstTileX = static_cast<int>(m_viewport.fLeft * scale / TilesManager::tileWidth()); - m_firstTileY = static_cast<int>(m_viewport.fTop * scale / TilesManager::tileHeight()); + + const float invTileContentWidth = scale / TilesManager::tileWidth(); + const float invTileContentHeight = scale / TilesManager::tileHeight(); + + m_viewportTileBounds.set( + static_cast<int>(floorf(viewport.fLeft * invTileContentWidth)), + static_cast<int>(floorf(viewport.fTop * invTileContentHeight)), + static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)), + static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight))); } } // namespace WebCore diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h index 3eaabb3..526061e 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.h +++ b/WebCore/platform/graphics/android/GLWebViewState.h @@ -165,10 +165,6 @@ public: double transitionTime(double currentTime); float transparency(double currentTime); void resetTransitionTime() { m_transitionTime = -1; } - int originalTilesPosX() const { return m_originalTilesPosX; } - void setOriginalTilesPosX(int pos) { m_originalTilesPosX = pos; } - int originalTilesPosY() const { return m_originalTilesPosY; } - void setOriginalTilesPosY(int pos) { m_originalTilesPosY = pos; } unsigned int paintBaseLayerContent(SkCanvas* canvas); void setBaseLayer(BaseLayerAndroid* layer, IntRect& rect); @@ -181,14 +177,17 @@ public: TiledPage* backPage(); void swapPages(); - void setViewport(SkRect& viewport, float scale); + // dimensions of the current base layer + int baseContentWidth(); + int baseContentHeight(); - // returns the number of tiles needed to cover the viewport - int nbTilesWidth() const { return m_nbTilesWidth; } - int nbTilesHeight() const { return m_nbTilesHeight; } + void setViewport(SkRect& viewport, float scale); - int firstTileX() const { return m_firstTileX; } - int firstTileY() const { return m_firstTileY; } + // a rect containing the coordinates of all tiles in the current viewport + const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; } + // a rect containing the viewportTileBounds before there was a scale change + const SkIRect& preZoomBounds() const { return m_preZoomBounds; } + void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; } unsigned int currentPictureCounter() const { return m_currentPictureCounter; } @@ -210,14 +209,10 @@ private: float m_futureScale; double m_updateTime; double m_transitionTime; - int m_originalTilesPosX; - int m_originalTilesPosY; android::Mutex m_tiledPageLock; SkRect m_viewport; - int m_nbTilesWidth; - int m_nbTilesHeight; - int m_firstTileX; - int m_firstTileY; + SkIRect m_viewportTileBounds; + SkIRect m_preZoomBounds; android::Mutex m_baseLayerLock; BaseLayerAndroid* m_baseLayer; unsigned int m_currentPictureCounter; diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp index eb500ac..295c849 100644 --- a/WebCore/platform/graphics/android/TiledPage.cpp +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -130,13 +130,13 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y for (int i = 0; i < tilesInRow; i++) { int x = firstTileX; - // If we are goingLeft, we want to schedule the tiles - // starting from the left (and to the right if not) + // If we are goingLeft, we want to schedule the tiles starting from the + // right (and to the left if not). This is because tiles are appended to + // the list and the texture uploader goes through the set front to back. if (goingLeft) - x += i; + x += (tilesInRow - 1) - i; else - x += (tilesInRow - 1) - i; - + x += i; BaseTile* currentTile = 0; BaseTile* availableTile = 0; @@ -165,13 +165,16 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y } } -void TiledPage::updateTileState(int firstTileX, int firstTileY) +void TiledPage::updateTileState(const SkIRect& tileBounds) { - if (!m_glWebViewState) + if (!m_glWebViewState || tileBounds.isEmpty()) return; - const int nbTilesWidth = m_glWebViewState->nbTilesWidth(); - const int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + const int nbTilesWidth = tileBounds.width(); + const int nbTilesHeight = tileBounds.height(); + + const int lastTileX = tileBounds.fRight - 1; + const int lastTileY = tileBounds.fBottom - 1; for (int x = 0; x < m_baseTileSize; x++) { @@ -189,15 +192,15 @@ void TiledPage::updateTileState(int firstTileX, int firstTileY) int dx = 0; int dy = 0; - if (firstTileX > tile.x()) - dx = firstTileX - tile.x(); - else if (firstTileX + (nbTilesWidth - 1) < tile.x()) - dx = tile.x() - firstTileX - (nbTilesWidth - 1); + if (tileBounds.fLeft > tile.x()) + dx = tileBounds.fLeft - tile.x(); + else if (lastTileX < tile.x()) + dx = tile.x() - lastTileX; - if (firstTileY > tile.y()) - dy = firstTileY - tile.y(); - else if (firstTileY + (nbTilesHeight - 1) < tile.y()) - dy = tile.y() - firstTileY - (nbTilesHeight - 1); + if (tileBounds.fTop > tile.y()) + dy = tileBounds.fTop - tile.y(); + else if (lastTileY < tile.y()) + dy = tile.y() - lastTileY; int d = std::max(dx, dy); @@ -210,27 +213,60 @@ void TiledPage::updateTileState(int firstTileX, int firstTileY) m_invalRegion.setEmpty(); } -void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firstTileY) +void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds) { if (!m_glWebViewState) return; // update the tiles distance from the viewport - updateTileState(firstTileX, firstTileY); + updateTileState(tileBounds); + + int firstTileX = tileBounds.fLeft; + int firstTileY = tileBounds.fTop; + int nbTilesWidth = tileBounds.width(); + int nbTilesHeight = tileBounds.height(); - int nbTilesWidth = m_glWebViewState->nbTilesWidth(); - int nbTilesHeight = m_glWebViewState->nbTilesHeight(); + const int lastTileX = tileBounds.fRight - 1; + const int lastTileY = tileBounds.fBottom - 1; + + const int baseContentHeight = m_glWebViewState->baseContentHeight(); + const int baseContentWidth = m_glWebViewState->baseContentWidth(); TileSet* highResSet = new TileSet(this, nbTilesHeight, nbTilesWidth); - // We chose to display tiles depending on the scroll direction: + // PREPARE OFF-SCREEN TILES FOR SMOOTHER SCROLLING + // if you are going down and you are not already at the bottom of the page + // go ahead and prepare the tiles just off-screen beneath the viewport. + if (goingDown && baseContentHeight > lastTileY * TilesManager::tileHeight()) + nbTilesHeight++; + // if you are going up and you are not already at the top of the page go + // ahead and prepare the tiles just off-screen above the viewport. + else if (!goingDown && firstTileY > 0) { + firstTileY--; + nbTilesHeight++; + } + // if you are going right and you are not already at the edge of the page go + // ahead and prepare the tiles just off-screen to the right of the viewport. + if (!goingLeft && baseContentWidth > lastTileX * TilesManager::tileWidth()) + nbTilesWidth++; + // if you are going left and you are not already at the edge of the page go + // ahead and prepare the tiles just off-screen to the left of the viewport. + else if (goingLeft && firstTileX > 0) { + firstTileX--; + nbTilesWidth++; + } + + + // We chose to prepare tiles depending on the scroll direction. Tiles are + // appended to the list and the texture uploader goes through the list front + // to back. So we append tiles in reverse order because the last additions + // to the are processed first. if (goingDown) { for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, highResSet); + prepareRow(goingLeft, nbTilesWidth, firstTileX, lastTileY - i, highResSet); } else { - int startingTileY = firstTileY + (nbTilesHeight - 1); for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, startingTileY - i, highResSet); + prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, highResSet); } // schedulePaintForTileSet will take ownership of the highResSet here, @@ -238,18 +274,13 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, int firstTileX, int firs TilesManager::instance()->schedulePaintForTileSet(highResSet); } -bool TiledPage::ready(int firstTileX, int firstTileY) +bool TiledPage::ready(const SkIRect& tileBounds) { if (!m_glWebViewState) return false; - int nbTilesWidth = m_glWebViewState->nbTilesWidth(); - int nbTilesHeight = m_glWebViewState->nbTilesHeight(); - - for (int i = 0; i < nbTilesHeight; i++) { - for (int j = 0; j < nbTilesWidth; j++) { - int x = j + firstTileX; - int y = i + firstTileY; + 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; @@ -258,7 +289,7 @@ bool TiledPage::ready(int firstTileX, int firstTileY) return true; } -void TiledPage::draw(float transparency, SkRect& viewport, int firstTileX, int firstTileY) +void TiledPage::draw(float transparency, SkRect& viewport, const SkIRect& tileBounds) { if (!m_glWebViewState) return; @@ -266,16 +297,10 @@ void TiledPage::draw(float transparency, SkRect& viewport, int firstTileX, int f const float tileWidth = TilesManager::tileWidth() * m_invScale; const float tileHeight = TilesManager::tileHeight() * m_invScale; - SkIRect viewportTilesRect; - viewportTilesRect.fLeft = firstTileX; - viewportTilesRect.fTop = firstTileY; - viewportTilesRect.fRight = firstTileY + m_glWebViewState->nbTilesWidth() + 1; - viewportTilesRect.fBottom = firstTileY + m_glWebViewState->nbTilesHeight() + 1; - XLOG("WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency); for (int j = 0; j < m_baseTileSize; j++) { BaseTile& tile = m_baseTiles[j]; - if(viewportTilesRect.contains(tile.x(), tile.y())) { + if(tileBounds.contains(tile.x(), tile.y())) { SkRect rect; rect.fLeft = tile.x() * tileWidth; diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h index 1edf5b4..fa310bf 100644 --- a/WebCore/platform/graphics/android/TiledPage.h +++ b/WebCore/platform/graphics/android/TiledPage.h @@ -60,11 +60,11 @@ public: TiledPage* sibling(); // prepare the page for display on the screen - void prepare(bool goingDown, bool goingLeft, int firstTileX, int firstTileY); + void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds); // check to see if the page is ready for display - bool ready(int firstTileX, int firstTileY); + bool ready(const SkIRect& tileBounds); // draw the page on the screen - void draw(float transparency, SkRect& viewport, int firstTileX, int firstTileY); + void draw(float transparency, SkRect& viewport, const SkIRect& tileBounds); // used by individual tiles to generate the bitmap for their tile unsigned int paintBaseLayerContent(SkCanvas*); @@ -77,7 +77,7 @@ public: void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount); private: - void updateTileState(int firstTileX, int firstTileY); + void updateTileState(const SkIRect& tileBounds); void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set); BaseTile* getBaseTile(int x, int y) const; |
