From 3a3a8a5cdda72d79add3d08082523d5115cb47a8 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Tue, 1 Feb 2011 03:58:44 -0800 Subject: Implement automatic texture size allocation for layers This fix several issues (3d transforms, etc.) and in general makes websites using layers snappier (gmail, etc.) bug:3367038 bug:3367048 Change-Id: Ib178416209c3636c7700296978a1f35a7a54ee22 --- .../platform/graphics/android/BaseLayerAndroid.cpp | 1 + WebCore/platform/graphics/android/LayerAndroid.cpp | 83 +++++++++++++++++++--- WebCore/platform/graphics/android/LayerAndroid.h | 9 ++- WebCore/platform/graphics/android/TilesManager.cpp | 14 +++- WebCore/platform/graphics/android/TilesManager.h | 2 + 5 files changed, 99 insertions(+), 10 deletions(-) (limited to 'WebCore/platform') 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/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 5d6d8ff..07a0e00 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& 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 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& 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/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index 81b0404..8cbca35 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -61,7 +61,9 @@ #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 { @@ -339,6 +341,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); diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index 92306b5..581d714 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -86,6 +86,8 @@ public: void resetTextureUsage(TiledPage* page); + int maxLayersAllocation(); + int maxLayerAllocation(); int maxTextureCount(); void setMaxTextureCount(int max); static float tileWidth(); -- cgit v1.1