diff options
Diffstat (limited to 'WebCore/platform')
7 files changed, 143 insertions, 43 deletions
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index d2d515a..b632664 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -314,6 +314,7 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect, scale = m_glWebViewState->futureScale(); } compositedRoot->setScale(scale); + compositedRoot->computeTextureSize(); compositedRoot->reserveGLTextures(); #ifdef DEBUG diff --git a/WebCore/platform/graphics/android/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp index 63fe730..38b747d 100644 --- a/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -288,7 +288,8 @@ void GLWebViewState::setViewport(SkRect& viewport, float scale) static_cast<int>(ceilf(viewport.fRight * invTileContentWidth)), static_cast<int>(ceilf(viewport.fBottom * invTileContentHeight))); - int maxTextureCount = (m_viewportTileBounds.width()+1)*(m_viewportTileBounds.height()+1)*2; + int maxTextureCount = (m_viewportTileBounds.width() + TilesManager::instance()->expandedTileBoundsX() * 2 + 1) * + (m_viewportTileBounds.height() + TilesManager::instance()->expandedTileBoundsY() * 2 + 1) * 2; TilesManager::instance()->setMaxTextureCount(maxTextureCount); m_tiledPageA->updateBaseTileSize(); m_tiledPageB->updateBaseTileSize(); diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 454fbf3..42104dc 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -585,7 +585,7 @@ bool LayerAndroid::needsTexture() && m_recordingPicture->width() && m_recordingPicture->height()); } -IntRect LayerAndroid::clippedRect() +IntRect LayerAndroid::clippedRect() const { IntRect r(0, 0, getWidth(), getHeight()); IntRect tr = drawTransform().mapRect(r); @@ -600,10 +600,20 @@ bool LayerAndroid::outsideViewport() m_layerTextureRect.height() == 0; } -int LayerAndroid::countTextureSize() +int LayerAndroid::fullTextureSize() const +{ + return getWidth() * m_scale * getHeight() * m_scale * 4; +} + +int LayerAndroid::clippedTextureSize() const { IntRect cr = clippedRect(); - int size = cr.width() * cr.height() * 4; + return cr.width() * cr.height() * 4; +} + +int LayerAndroid::countTextureSize() +{ + int size = clippedTextureSize(); int count = this->countChildren(); for (int i = 0; i < count; i++) size += getChild(i)->countTextureSize(); @@ -619,6 +629,67 @@ int LayerAndroid::nbLayers() return nb; } +void LayerAndroid::collect(Vector<LayerAndroid*>& layers, int& size) +{ + m_layerTextureRect = clippedRect(); + if (!outsideViewport()) { + layers.append(this); + size += fullTextureSize(); + } + int count = this->countChildren(); + for (int i = 0; i < count; i++) + getChild(i)->collect(layers, size); +} + +static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroid* b) +{ + const int sizeA = a->fullTextureSize(); + const int sizeB = b->fullTextureSize(); + return sizeA > sizeB; +} + +void LayerAndroid::computeTextureSize() +{ + // First, we collect the layers, computing m_layerTextureRect + // as being clipped against the viewport + Vector <LayerAndroid*> layers; + int total = 0; + collect(layers, total); + + // Then we sort them by the size the full texture would need + std::stable_sort(layers.begin(), layers.end(), compareLayerFullSize); + + // Now, let's determinate which layer can use a full texture + int max = TilesManager::instance()->maxLayersAllocation(); + int maxLayerSize = TilesManager::instance()->maxLayerAllocation(); + XLOG("*** layers sorted by size ***"); + XLOG("total memory needed: %d bytes (%d Mb), max %d Mb", + total, total / 1024 / 1024, max / 1024 / 1024); + for (unsigned int i = 0; i < layers.size(); i++) { + LayerAndroid* layer = layers[i]; + bool clipped = true; + // If we are under the maximum, and the layer inspected + // needs a texture less than the maxLayerSize, use the full texture. + if ((total < max) && + (layer->fullTextureSize() < maxLayerSize)) { + IntRect full(0, 0, layer->getWidth(), layer->getHeight()); + layer->m_layerTextureRect = full; + clipped = false; + } else { + // Otherwise, the layer is clipped; update the total + total -= layer->fullTextureSize(); + total += layer->clippedTextureSize(); + } + XLOG("Layer %d (%.2f, %.2f) %d bytes (clipped: %s)", + layer->uniqueId(), layer->getWidth(), layer->getHeight(), + layer->fullTextureSize(), + clipped ? "YES" : "NO"); + } + XLOG("total memory used after clipping: %d bytes (%d Mb), max %d Mb", + total, total / 1024 / 1024, max / 1024 / 1024); + XLOG("*** end of sorted layers ***"); +} + void LayerAndroid::showLayers(int indent) { IntRect cr = clippedRect(); @@ -655,14 +726,10 @@ void LayerAndroid::reserveGLTextures() if (!needsTexture()) return; - LayerTexture* reservedTexture = 0; - - // Compute the layer size & position we need (clipped to the viewport) - m_layerTextureRect = clippedRect(); - if (outsideViewport()) return; + LayerTexture* reservedTexture = 0; reservedTexture = TilesManager::instance()->getExistingTextureForLayer( this, m_layerTextureRect); diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index f4fea49..53e513b 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -102,7 +102,7 @@ public: void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } FloatPoint translation() const; SkRect bounds() const; - IntRect clippedRect(); + IntRect clippedRect() const; bool outsideViewport(); // Debug/info functions @@ -110,6 +110,13 @@ public: int nbLayers(); void showLayers(int indent = 0); + // Texture size functions + void computeTextureSize(); + void collect(Vector<LayerAndroid*>& layers, + int& size); + int clippedTextureSize() const; + int fullTextureSize() const; + // called on the root layer void reserveGLTextures(); void createGLTextures(); diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp index b6d2205..620aa6f 100644 --- a/WebCore/platform/graphics/android/TiledPage.cpp +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -244,43 +244,29 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound int nbTilesWidth = tileBounds.width(); int nbTilesHeight = tileBounds.height(); - const int lastTileX = tileBounds.fRight - 1; - const int lastTileY = tileBounds.fBottom - 1; + int lastTileX = tileBounds.fRight - 1; + int lastTileY = tileBounds.fBottom - 1; const int baseContentHeight = m_glWebViewState->baseContentHeight(); const int baseContentWidth = m_glWebViewState->baseContentWidth(); TileSet* highResSet = new TileSet(this, nbTilesHeight, nbTilesWidth); + // Expand number of tiles to allow tiles outside of viewport to be prepared for + // smoother scrolling. int nTilesToPrepare = nbTilesWidth * nbTilesHeight; int nMaxTilesPerPage = m_baseTileSize / 2; - - // 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. - // Ensure we have enough tiles to do this with. - if (nTilesToPrepare + nbTilesWidth <= nMaxTilesPerPage) { - 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++; - } + int expandX = TilesManager::instance()->expandedTileBoundsX(); + int expandY = TilesManager::instance()->expandedTileBoundsY(); + if (nTilesToPrepare + (nbTilesHeight * expandX * 2) <= nMaxTilesPerPage) { + firstTileX -= expandX; + lastTileX += expandX; + nbTilesWidth += expandX * 2; } - - if (nTilesToPrepare + nbTilesHeight <= nMaxTilesPerPage) { - // 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++; - } + if (nTilesToPrepare + (nbTilesWidth * expandY * 2) <= nMaxTilesPerPage) { + firstTileY -= expandY; + lastTileY += expandY; + nbTilesHeight += expandY * 2; } // We chose to prepare tiles depending on the scroll direction. Tiles are @@ -331,10 +317,16 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds) const float tileWidth = TilesManager::tileWidth() * m_invScale; const float tileHeight = TilesManager::tileHeight() * m_invScale; + SkIRect actualTileBounds = tileBounds; + actualTileBounds.fTop -= TilesManager::instance()->expandedTileBoundsY(); + actualTileBounds.fBottom += TilesManager::instance()->expandedTileBoundsY(); + actualTileBounds.fLeft -= TilesManager::instance()->expandedTileBoundsX(); + actualTileBounds.fRight += TilesManager::instance()->expandedTileBoundsX(); + 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 (tileBounds.contains(tile.x(), tile.y())) { + if (actualTileBounds.contains(tile.x(), tile.y())) { SkRect rect; rect.fLeft = tile.x() * tileWidth; diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 81b0404..d64a0b1 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -54,14 +54,18 @@ // one viewport, otherwise the allocation may stall. // We need n textures for one TiledPage, and another n textures for the // second page used when scaling. -// In our case, we use 300x300 textures. On the tablet, this equals to -// at least 24 (6 * 4) textures, hence 48. -#define MAX_TEXTURE_ALLOCATION 48 +// In our case, we use 300x300 textures. On the tablet, this equates to +// at least 5 * 3 = 15 textures. We can also enable offscreen textures +#define EXPANDED_TILE_BOUNDS_X 1 +#define EXPANDED_TILE_BOUNDS_Y 4 +#define MAX_TEXTURE_ALLOCATION (5+EXPANDED_TILE_BOUNDS_X*2)*(3+EXPANDED_TILE_BOUNDS_Y*2)*2 #define TILE_WIDTH 300 #define TILE_HEIGHT 300 // Define a maximum amount of ram used by layers -#define MAX_LAYERS_ALLOCATION 20971520 // 20Mb +#define MAX_LAYERS_ALLOCATION 33554432 // 32Mb +// Define a maximum amount of ram used by one layer +#define MAX_LAYER_ALLOCATION 8388608 // 8Mb #define BYTES_PER_PIXEL 4 // 8888 config namespace WebCore { @@ -69,6 +73,7 @@ namespace WebCore { TilesManager::TilesManager() : m_layersMemoryUsage(0) , m_maxTextureCount(0) + , m_expandedTileBounds(false) , m_generatorReady(false) { XLOG("TilesManager ctor"); @@ -339,6 +344,16 @@ LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const Int return texture; } +int TilesManager::maxLayersAllocation() +{ + return MAX_LAYERS_ALLOCATION; +} + +int TilesManager::maxLayerAllocation() +{ + return MAX_LAYER_ALLOCATION; +} + int TilesManager::maxTextureCount() { android::Mutex::Autolock lock(m_texturesLock); @@ -366,6 +381,14 @@ float TilesManager::tileHeight() return TILE_HEIGHT; } +int TilesManager::expandedTileBoundsX() { + return m_expandedTileBounds ? EXPANDED_TILE_BOUNDS_X : 0; +} + +int TilesManager::expandedTileBoundsY() { + return m_expandedTileBounds ? EXPANDED_TILE_BOUNDS_Y : 0; +} + TilesManager* TilesManager::instance() { if (!gInstance) { diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index 92306b5..113cc62 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -86,13 +86,21 @@ public: void resetTextureUsage(TiledPage* page); + int maxLayersAllocation(); + int maxLayerAllocation(); int maxTextureCount(); void setMaxTextureCount(int max); static float tileWidth(); static float tileHeight(); + int expandedTileBoundsX(); + int expandedTileBoundsY(); void allocateTiles(); + void setExpandedTileBounds(bool enabled) { + m_expandedTileBounds = enabled; + } + private: TilesManager(); @@ -112,6 +120,7 @@ private: unsigned int m_totalMaxTextureSize; int m_maxTextureCount; + bool m_expandedTileBounds; bool m_generatorReady; |