summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android/TiledTexture.cpp
diff options
context:
space:
mode:
authorNicolas Roard <nicolasroard@google.com>2011-10-20 15:55:34 -0700
committerNicolas Roard <nicolasroard@google.com>2011-10-20 16:47:41 -0700
commitf65ed48034d37597dc4b191a79781ae49d2cfc99 (patch)
tree6fac77320f6317983598e52033a59c30625e2829 /Source/WebCore/platform/graphics/android/TiledTexture.cpp
parent8cc0fa17a42ae1dec75fe8ab00d5baa75e46499e (diff)
downloadexternal_webkit-f65ed48034d37597dc4b191a79781ae49d2cfc99.zip
external_webkit-f65ed48034d37597dc4b191a79781ae49d2cfc99.tar.gz
external_webkit-f65ed48034d37597dc4b191a79781ae49d2cfc99.tar.bz2
Implement dual textures for layers to handle zooming correctly.
We add a new class, DualTiledTexture, that encapsulate two TiledTextures and manage them according to the current scale factor. bug:5492874 Change-Id: I4ba3ff539f9242ae5102189e9623e1535e9cc28f
Diffstat (limited to 'Source/WebCore/platform/graphics/android/TiledTexture.cpp')
-rw-r--r--Source/WebCore/platform/graphics/android/TiledTexture.cpp145
1 files changed, 120 insertions, 25 deletions
diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
index ce4dc7f..87996ab 100644
--- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp
+++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp
@@ -54,7 +54,28 @@
namespace WebCore {
-void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSwap)
+bool TiledTexture::ready() {
+ bool tilesAllReady = true;
+ bool tilesVisible = false;
+ for (unsigned int i = 0; i < m_tiles.size(); i++) {
+ BaseTile* tile = m_tiles[i];
+ if (tile->isTileVisible(m_area) && !tile->isTileReady()) {
+ tilesAllReady = false;
+ break;
+ }
+ if (tile->isTileVisible(m_area))
+ tilesVisible = true;
+ }
+ // For now, if no textures are available, consider ourselves as ready
+ // in order to unblock the zooming process.
+ // FIXME: have a better system -- maybe keeping the last scale factor
+ // able to fully render everything
+ return !TilesManager::instance()->layerTexturesRemain()
+ || (tilesAllReady && tilesVisible);
+}
+
+void TiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
+ bool startFastSwap, IntRect& visibleArea)
{
if (!m_surface)
return;
@@ -63,11 +84,10 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSw
return;
// first, how many tiles do we need
- IntRect visibleArea = m_surface->visibleArea();
- IntRect area(visibleArea.x() * m_surface->scale(),
- visibleArea.y() * m_surface->scale(),
- ceilf(visibleArea.width() * m_surface->scale()),
- ceilf(visibleArea.height() * m_surface->scale()));
+ IntRect area(visibleArea.x() * scale,
+ visibleArea.y() * scale,
+ ceilf(visibleArea.width() * scale),
+ ceilf(visibleArea.height() * scale));
if (area.width() == 0 && area.height() == 0) {
m_area.setWidth(0);
@@ -85,8 +105,8 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSw
m_area.setWidth(ceilf(right) - m_area.x());
m_area.setHeight(ceilf(bottom) - m_area.y());
- XLOG("for TiledTexture %p, we have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
- this,
+ XLOG("for TiledTexture %p, we prepare with scale %.2f, have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
+ this, scale,
visibleArea.x(), visibleArea.y(),
visibleArea.width(), visibleArea.height(),
m_area.x(), m_area.y(),
@@ -95,20 +115,13 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSw
bool goingDown = m_prevTileY < m_area.y();
m_prevTileY = m_area.y();
- if (m_surface->scale() != m_prevScale)
- TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(m_surface->scale()));
+ if (scale != m_scale)
+ TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(this, scale));
- m_prevScale = m_surface->scale();
+ m_scale = scale;
// unlock if tiles all ready
- bool tilesAllReady = true;
- for (unsigned int i = 0; i < m_tiles.size(); i++) {
- BaseTile* tile = m_tiles[i];
- if (tile->isTileVisible(m_area) && !tile->isTileReady()) {
- tilesAllReady = false;
- break;
- }
- }
+ bool tilesAllReady = ready();
// startFastSwap=true will swap all ready tiles each
// frame until all visible tiles are up to date
@@ -173,7 +186,7 @@ void TiledTexture::prepareTile(bool repaint, int x, int y)
}
XLOG("preparing tile %p, painter is this %p", tile, this);
- tile->setContents(this, x, y, m_surface->scale());
+ tile->setContents(this, x, y, m_scale);
// TODO: move below (which is largely the same for layers / tiled page) into
// prepare() function
@@ -210,10 +223,9 @@ bool TiledTexture::draw()
TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
#endif
- float m_invScale = 1 / m_surface->scale();
+ float m_invScale = 1 / m_scale;
const float tileWidth = TilesManager::layerTileWidth() * m_invScale;
const float tileHeight = TilesManager::layerTileHeight() * m_invScale;
- XLOG("draw tile %x, tiles %d", this, m_tiles.size());
bool askRedraw = false;
for (unsigned int i = 0; i < m_tiles.size(); i++) {
@@ -226,10 +238,10 @@ bool TiledTexture::draw()
rect.fTop = tile->y() * tileHeight;
rect.fRight = rect.fLeft + tileWidth;
rect.fBottom = rect.fTop + tileHeight;
- XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f [ready: %d] dirty: %d",
+ XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f vs %.2f [ready: %d] dirty: %d",
i, this, tile->painter(), tile, tile->x(), tile->y(),
- tile->scale(), tile->isTileReady(), tile->isDirty());
- tile->draw(m_surface->opacity(), rect, m_surface->scale());
+ tile->scale(), m_scale, tile->isTileReady(), tile->isDirty());
+ tile->draw(m_surface->opacity(), rect, m_scale);
#ifdef DEBUG
TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
#endif
@@ -260,6 +272,13 @@ void TiledTexture::removeTiles()
for (unsigned int i = 0; i < m_tiles.size(); i++) {
delete m_tiles[i];
}
+ m_tiles.clear();
+}
+
+void TiledTexture::discardTextures()
+{
+ for (unsigned int i = 0; i < m_tiles.size(); i++)
+ m_tiles[i]->discardTextures();
}
bool TiledTexture::owns(BaseTileTexture* texture)
@@ -274,4 +293,80 @@ bool TiledTexture::owns(BaseTileTexture* texture)
return false;
}
+DualTiledTexture::DualTiledTexture(PaintedSurface* surface)
+{
+ m_textureA = new TiledTexture(surface);
+ m_textureB = new TiledTexture(surface);
+ m_frontTexture = m_textureA;
+ m_backTexture = m_textureB;
+ m_scale = -1;
+ m_futureScale = -1;
+ m_zooming = false;
+}
+
+DualTiledTexture::~DualTiledTexture()
+{
+ delete m_textureA;
+ delete m_textureB;
+}
+
+void DualTiledTexture::prepare(GLWebViewState* state, float scale, bool repaint,
+ bool startFastSwap, IntRect& visibleArea)
+{
+ // If we are zooming, we will use the previously used area, to prevent the
+ // frontTexture to try to allocate more tiles than what it has already
+ if (!m_zooming)
+ m_preZoomVisibleArea = visibleArea;
+
+ if (m_futureScale != scale) {
+ m_futureScale = scale;
+ m_zoomUpdateTime = WTF::currentTime() + DualTiledTexture::s_zoomUpdateDelay;
+ m_zooming = true;
+ }
+
+ XLOG("\n*** %x Drawing with scale %.2f, futureScale: %.2f, zooming: %d",
+ this, scale, m_futureScale, m_zooming);
+
+ if (m_scale > 0)
+ m_frontTexture->prepare(state, m_scale, repaint, startFastSwap, m_preZoomVisibleArea);
+
+ // If we had a scheduled update
+ if (m_zooming && m_zoomUpdateTime < WTF::currentTime()) {
+ m_backTexture->prepare(state, m_futureScale, repaint, startFastSwap, visibleArea);
+ if (m_backTexture->ready()) {
+ swap();
+ m_zooming = false;
+ }
+ }
+}
+
+void DualTiledTexture::swap()
+{
+ m_frontTexture = m_frontTexture == m_textureA ? m_textureB : m_textureA;
+ m_backTexture = m_backTexture == m_textureA ? m_textureB : m_textureA;
+ m_scale = m_futureScale;
+ m_backTexture->discardTextures();
+}
+
+bool DualTiledTexture::draw()
+{
+ bool needsRepaint = m_frontTexture->draw();
+ needsRepaint |= m_zooming;
+ needsRepaint |= (m_scale <= 0);
+ return needsRepaint;
+}
+
+void DualTiledTexture::update(const SkRegion& dirtyArea, SkPicture* picture)
+{
+ m_backTexture->update(dirtyArea, picture);
+ m_frontTexture->update(dirtyArea, picture);
+}
+
+bool DualTiledTexture::owns(BaseTileTexture* texture)
+{
+ bool owns = m_textureA->owns(texture);
+ owns |= m_textureB->owns(texture);
+ return owns;
+}
+
} // namespace WebCore