diff options
author | Nicolas Roard <nicolasroard@google.com> | 2011-10-20 17:53:57 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-10-20 17:53:57 -0700 |
commit | 3d2c72b84e33ed0463749f0b75561dd586e45a59 (patch) | |
tree | 6f1da645ac6dca5207d967fe11a9df690058af6c | |
parent | 4c3a209f7fe5d15e4cfbe8f82c0a057e5682cd7c (diff) | |
parent | 6032fa428d725097ea29fc85fc1b2c965094772b (diff) | |
download | external_webkit-3d2c72b84e33ed0463749f0b75561dd586e45a59.zip external_webkit-3d2c72b84e33ed0463749f0b75561dd586e45a59.tar.gz external_webkit-3d2c72b84e33ed0463749f0b75561dd586e45a59.tar.bz2 |
am 6032fa42: Merge "Implement dual textures for layers to handle zooming correctly." into ics-mr0
* commit '6032fa428d725097ea29fc85fc1b2c965094772b':
Implement dual textures for layers to handle zooming correctly.
8 files changed, 175 insertions, 41 deletions
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index f931f22..7b43305 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -86,6 +86,7 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex) , m_goingLeft(false) , m_expandedTileBoundsX(0) , m_expandedTileBoundsY(0) + , m_scale(1) { m_viewport.setEmpty(); m_futureViewportTileBounds.setEmpty(); @@ -405,6 +406,7 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, IntRect& webViewRect, int titleBarHeight, IntRect& clip, float scale, bool* buffersSwappedPtr) { + m_scale = scale; TilesManager::instance()->getProfiler()->nextFrame(viewport.fLeft, viewport.fTop, viewport.fRight, diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 2f7e16d..b2aab88 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -230,6 +230,8 @@ public: int expandedTileBoundsX() { return m_expandedTileBoundsX; } int expandedTileBoundsY() { return m_expandedTileBoundsY; } + float scale() { return m_scale; } + private: void inval(const IntRect& rect); // caller must hold m_baseLayerLock void invalRegion(const SkRegion& region); @@ -273,6 +275,8 @@ private: int m_expandedTileBoundsX; int m_expandedTileBoundsY; + + float m_scale; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h index 57bbd8b..65d20f2 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h @@ -52,17 +52,20 @@ private: class ScaleFilter : public OperationFilter { public: - ScaleFilter(float scale) : m_scale(scale) {} + ScaleFilter(TilePainter* painter, float scale) + : m_painter(painter) + , m_scale(scale) {} virtual bool check(QueuedOperation* operation) { if (operation->type() == QueuedOperation::PaintTile) { PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); - if (op->scale() != m_scale) + if ((op->painter() == m_painter) && (op->scale() != m_scale)) return true; } return false; } private: + TilePainter* m_painter; float m_scale; }; diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp index c5ed38c..0957c0c 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp @@ -68,7 +68,7 @@ PaintedSurface::PaintedSurface(LayerAndroid* layer) #ifdef DEBUG_COUNT ClassTracker::instance()->increment("PaintedSurface"); #endif - m_tiledTexture = new TiledTexture(this); + m_tiledTexture = new DualTiledTexture(this); if (layer && layer->picture()) m_updateManager.updatePicture(layer->picture()); } @@ -142,7 +142,6 @@ void PaintedSurface::prepare(GLWebViewState* state) m_layer->uniqueId(), m_layer, m_layer->getScale()); - float scale = m_layer->getScale(); int w = m_layer->getSize().width(); int h = m_layer->getSize().height(); @@ -154,13 +153,13 @@ void PaintedSurface::prepare(GLWebViewState* state) computeVisibleArea(); - if (scale != m_scale) - m_scale = scale; + m_scale = state->scale(); - XLOG("layer %d %x prepared at size (%d, %d) @ scale %.2f", m_layer->uniqueId(), - m_layer, w, h, scale); + XLOGC("%x layer %d %x prepared at size (%d, %d) @ scale %.2f", this, m_layer->uniqueId(), + m_layer, w, h, m_scale); - m_tiledTexture->prepare(state, m_pictureUsed != m_layer->pictureUsed(), startFastSwap); + m_tiledTexture->prepare(state, m_scale, m_pictureUsed != m_layer->pictureUsed(), + startFastSwap, m_visibleArea); } bool PaintedSurface::draw() diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h index 5df76db..761be74 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.h +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h @@ -75,13 +75,12 @@ public: float scale() { return m_scale; } float opacity(); unsigned int pictureUsed() { return m_pictureUsed; } - TiledTexture* texture() { return m_tiledTexture; } private: UpdateManager m_updateManager; LayerAndroid* m_layer; - TiledTexture* m_tiledTexture; + DualTiledTexture* m_tiledTexture; IntRect m_area; IntRect m_visibleArea; 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 diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index aa82e36..206961b 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.h +++ b/Source/WebCore/platform/graphics/android/TiledTexture.h @@ -49,7 +49,7 @@ public: : m_surface(surface) , m_prevTileX(0) , m_prevTileY(0) - , m_prevScale(1) + , m_scale(1) , m_swapWhateverIsReady(false) { m_dirtyRegion.setEmpty(); @@ -65,7 +65,8 @@ public: removeTiles(); }; - void prepare(GLWebViewState* state, bool repaint, bool startFastSwap); + void prepare(GLWebViewState* state, float scale, bool repaint, + bool startFastSwap, IntRect& visibleArea); bool draw(); void prepareTile(bool repaint, int x, int y); @@ -74,6 +75,7 @@ public: BaseTile* getTile(int x, int y); void removeTiles(); + void discardTextures(); bool owns(BaseTileTexture* texture); // TilePainter methods @@ -81,6 +83,11 @@ public: virtual void paintExtra(SkCanvas*); virtual const TransformationMatrix* transform(); + float scale() { return m_scale; } + bool ready(); + + PaintedSurface* surface() { return m_surface; } + private: bool tileIsVisible(BaseTile* tile); @@ -96,11 +103,36 @@ private: int m_prevTileX; int m_prevTileY; - float m_prevScale; + float m_scale; bool m_swapWhateverIsReady; }; +class DualTiledTexture { +public: + DualTiledTexture(PaintedSurface* surface); + ~DualTiledTexture(); + void prepare(GLWebViewState* state, float scale, bool repaint, + bool startFastSwap, IntRect& area); + void swap(); + bool draw(); + void update(const SkRegion& dirtyArea, SkPicture* picture); + bool owns(BaseTileTexture* texture); +private: + // Delay before we schedule a new tile at the new scale factor + static const double s_zoomUpdateDelay = 0.2; // 200 ms + + TiledTexture* m_frontTexture; + TiledTexture* m_backTexture; + TiledTexture* m_textureA; + TiledTexture* m_textureB; + float m_scale; + float m_futureScale; + double m_zoomUpdateTime; + bool m_zooming; + IntRect m_preZoomVisibleArea; +}; + } // namespace WebCore #endif // TiledTexture_h diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 74cc764..dd2b169 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -277,7 +277,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) const unsigned int max = availableTexturePool->size(); for (unsigned int i = 0; i < max; i++) { BaseTileTexture* texture = (*availableTexturePool)[i]; - TextureOwner* currentOwner = texture->owner(); + BaseTile* currentOwner = static_cast<BaseTile*>(texture->owner()); if (texture->busy()) { // don't bother, since the acquire() will likely fail @@ -296,7 +296,7 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) continue; } - if (currentOwner->page() == owner->page() && texture->scale() != owner->scale()) { + if (currentOwner->painter() == owner->painter() && texture->scale() != owner->scale()) { // if we render the back page with one scale, then another while // still zooming, we recycle the tiles with the old scale instead of // taking ones from the front page |