summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/graphics/android/BaseLayerAndroid.cpp1
-rw-r--r--WebCore/platform/graphics/android/GLWebViewState.cpp3
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp83
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h9
-rw-r--r--WebCore/platform/graphics/android/TiledPage.cpp50
-rw-r--r--WebCore/platform/graphics/android/TilesManager.cpp31
-rw-r--r--WebCore/platform/graphics/android/TilesManager.h9
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;