diff options
author | John Reck <jreck@google.com> | 2011-03-23 18:02:27 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2011-03-25 13:25:16 -0700 |
commit | 417789b7c56928a5fcb610583346d07ffa380900 (patch) | |
tree | 3f8902d06b229fa826b866778bfc57cf852f9742 /WebCore/platform | |
parent | 78eb447490d235178fafa5bd046918ffe965003f (diff) | |
download | external_webkit-417789b7c56928a5fcb610583346d07ffa380900.zip external_webkit-417789b7c56928a5fcb610583346d07ffa380900.tar.gz external_webkit-417789b7c56928a5fcb610583346d07ffa380900.tar.bz2 |
My attempt at a smarter tile manager
Removes TileSets and queues tiles individually
Uses a priority queue to determine which tiles to render first
Stops rendering the front tile page if we are prepping the back one
Limits queue spam by tracking which tiles are already in the queue
Change-Id: I2f2c9539e0d8a421ac7f1f4cb80ee831b9894293
Diffstat (limited to 'WebCore/platform')
-rw-r--r-- | WebCore/platform/graphics/android/BaseLayerAndroid.cpp | 14 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/BaseTile.cpp | 20 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/BaseTile.h | 5 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/LayerAndroid.cpp | 2 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/PaintTileOperation.cpp (renamed from WebCore/platform/graphics/android/TileSet.cpp) | 86 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/PaintTileOperation.h (renamed from WebCore/platform/graphics/android/PaintTileSetOperation.h) | 30 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/QueuedOperation.h | 17 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TexturesGenerator.cpp | 102 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TexturesGenerator.h | 6 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TileSet.h | 77 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TiledPage.cpp | 135 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TiledPage.h | 11 | ||||
-rw-r--r-- | WebCore/platform/graphics/android/TilesManager.h | 11 |
13 files changed, 240 insertions, 276 deletions
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 1786d64..cf8b6fa 100644 --- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -163,13 +163,19 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double zooming = true; } + // Display the current page + TiledPage* tiledPage = m_glWebViewState->frontPage(); + tiledPage->setScale(m_glWebViewState->currentScale()); + // Let's prepare the page if needed if (prepareNextTiledPage) { TiledPage* nextTiledPage = m_glWebViewState->backPage(); nextTiledPage->setScale(scale); m_glWebViewState->setFutureViewport(viewportTileBounds); m_glWebViewState->lockBaseLayerUpdate(); - nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, true); + nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds); + // Cancel pending paints for the foreground page + TilesManager::instance()->removePaintOperationsForPage(tiledPage, false); } float transparency = 1; @@ -205,9 +211,6 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double } } - // Display the current page - TiledPage* tiledPage = m_glWebViewState->frontPage(); - tiledPage->setScale(m_glWebViewState->currentScale()); const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds(); TiledPage* nextTiledPage = m_glWebViewState->backPage(); @@ -240,7 +243,8 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, double if (!zooming) m_glWebViewState->unlockBaseLayerUpdate(); - tiledPage->prepare(goingDown, goingLeft, preZoomBounds, true); + if (!prepareNextTiledPage) + tiledPage->prepare(goingDown, goingLeft, preZoomBounds); tiledPage->draw(transparency, preZoomBounds); } diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index 391e87b..be0ccf6 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -66,6 +66,7 @@ BaseTile::BaseTile() , m_texture(0) , m_scale(1) , m_dirty(true) + , m_repaintPending(false) , m_usable(true) , m_lastDirtyPicture(0) , m_fullRepaintA(true) @@ -166,12 +167,31 @@ bool BaseTile::isDirty() return m_dirty; } +bool BaseTile::isRepaintPending() +{ + android::AutoMutex lock(m_atomicSync); + return m_repaintPending; +} + +void BaseTile::setRepaintPending(bool pending) +{ + android::AutoMutex lock(m_atomicSync); + m_repaintPending = pending; +} + void BaseTile::setUsedLevel(int usedLevel) { if (m_texture) m_texture->setUsedLevel(usedLevel); } +int BaseTile::usedLevel() +{ + if (m_texture) + return m_texture->usedLevel(); + return -1; +} + void BaseTile::draw(float transparency, SkRect& rect) { if (m_x < 0 || m_y < 0) diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h index c50f6f5..709e3cf 100644 --- a/WebCore/platform/graphics/android/BaseTile.h +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -72,6 +72,7 @@ public: void reserveTexture(); void setUsedLevel(int); + int usedLevel(); bool isTileReady(); void draw(float transparency, SkRect& rect); @@ -89,6 +90,8 @@ public: void markAsDirty(const unsigned int pictureCount, const SkRegion& dirtyArea); bool isDirty(); + bool isRepaintPending(); + void setRepaintPending(bool pending); void setUsable(bool usable); float scale() const { return m_scale; } void setScale(float scale); @@ -114,6 +117,8 @@ private: float m_scale; // used to signal that the that the tile is out-of-date and needs to be redrawn bool m_dirty; + // used to signal that a repaint is pending + bool m_repaintPending; // used to signal whether or not the draw can use this tile. bool m_usable; // stores the id of the latest picture from webkit that caused this tile to diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 433e7ec..0d71eec 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -890,7 +890,7 @@ void LayerAndroid::createGLTextures() uniqueId(), this, m_dirty, m_reservedTexture, m_reservedTexture->rect().width(), m_reservedTexture->rect().height()); PaintLayerOperation* operation = new PaintLayerOperation(this); - TilesManager::instance()->scheduleOperation(operation, !m_drawingTexture); + TilesManager::instance()->scheduleOperation(operation); } else { XLOG("We don't schedule a paint for layer %d (%x), because we already sent a request", uniqueId(), this); diff --git a/WebCore/platform/graphics/android/TileSet.cpp b/WebCore/platform/graphics/android/PaintTileOperation.cpp index 1214aa2..222b69b 100644 --- a/WebCore/platform/graphics/android/TileSet.cpp +++ b/WebCore/platform/graphics/android/PaintTileOperation.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2010, The Android Open Source Project + * Copyright 2011, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,64 +24,58 @@ */ #include "config.h" -#include "TileSet.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "ClassTracker.h" -#include "TilesManager.h" - -#ifdef DEBUG - -#include <cutils/log.h> -#include <wtf/CurrentTime.h> -#include <wtf/text/CString.h> - -#undef XLOG -#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TileSet", __VA_ARGS__) - -#else - -#undef XLOG -#define XLOG(...) - -#endif // DEBUG +#include "PaintTileOperation.h" namespace WebCore { -TileSet::TileSet(TiledPage* tiledPage, int rows, int cols) - : m_tiledPage(tiledPage) - , m_nbRows(rows) - , m_nbCols(cols) +PaintTileOperation::PaintTileOperation(BaseTile* tile) + : QueuedOperation(QueuedOperation::PaintTile, tile->page()) + , m_tile(tile) { -#ifdef DEBUG_COUNT - ClassTracker::instance()->increment("TileSet"); -#endif + if (m_tile) + m_tile->setRepaintPending(true); } -TileSet::~TileSet() +PaintTileOperation::~PaintTileOperation() { -#ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("TileSet"); -#endif + if (m_tile) { + m_tile->setRepaintPending(false); + m_tile = 0; + } } -bool TileSet::operator==(const TileSet& set) +bool PaintTileOperation::operator==(const QueuedOperation* operation) { - return m_tiledPage == set.m_tiledPage - && m_nbRows == set.m_nbRows - && m_nbCols == set.m_nbCols; + if (operation->type() != type()) + return false; + const PaintTileOperation* op = static_cast<const PaintTileOperation*>(operation); + return op->m_tile == m_tile; } - -void TileSet::paint() +void PaintTileOperation::run() { - XLOG("%x, painting %d tiles", this, m_tiles.size()); - for (unsigned int i = 0; i < m_tiles.size(); i++) - m_tiles[i]->paintBitmap(); - XLOG("%x, end of painting %d tiles", this, m_tiles.size()); + if (m_tile) { + m_tile->paintBitmap(); + m_tile->setRepaintPending(false); + m_tile = 0; + } } -} // namespace WebCore +int PaintTileOperation::priority() +{ + if (!m_tile || m_tile->usedLevel() < 0) + return -1; + bool goingDown = m_tile->page()->scrollingDown(); + SkIRect *rect = m_tile->page()->expandedTileBounds(); + int firstTileX = rect->fLeft; + int nbTilesWidth = rect->width(); + int priority = m_tile->x() - firstTileX; + if (goingDown) + priority += (rect->fBottom - m_tile->y()) * nbTilesWidth; + else + priority += (m_tile->y() - rect->fTop) * nbTilesWidth; + priority += m_tile->usedLevel() * 100000; + return priority; +} -#endif // USE(ACCELERATED_COMPOSITING) +} diff --git a/WebCore/platform/graphics/android/PaintTileSetOperation.h b/WebCore/platform/graphics/android/PaintTileOperation.h index fba7220..0920f32 100644 --- a/WebCore/platform/graphics/android/PaintTileSetOperation.h +++ b/WebCore/platform/graphics/android/PaintTileOperation.h @@ -27,33 +27,19 @@ #define PaintTileSetOperation_h #include "QueuedOperation.h" -#include "TileSet.h" namespace WebCore { -class PaintTileSetOperation : public QueuedOperation { +class PaintTileOperation : public QueuedOperation { public: - PaintTileSetOperation(TileSet* set) - : QueuedOperation(QueuedOperation::PaintTileSet, set->page()) - , m_set(set) {} - virtual ~PaintTileSetOperation() - { - delete m_set; - } - virtual bool operator==(const QueuedOperation* operation) - { - if (operation->type() != type()) - return false; - const PaintTileSetOperation* op = static_cast<const PaintTileSetOperation*>(operation); - return op->m_set == m_set; - } - virtual void run() - { - if (m_set) - m_set->paint(); - } + PaintTileOperation(BaseTile* tile); + virtual ~PaintTileOperation(); + virtual bool operator==(const QueuedOperation* operation); + virtual void run(); + virtual int priority(); + private: - TileSet* m_set; + BaseTile* m_tile; }; } diff --git a/WebCore/platform/graphics/android/QueuedOperation.h b/WebCore/platform/graphics/android/QueuedOperation.h index 089483d..98f3e2f 100644 --- a/WebCore/platform/graphics/android/QueuedOperation.h +++ b/WebCore/platform/graphics/android/QueuedOperation.h @@ -32,13 +32,14 @@ namespace WebCore { class QueuedOperation { public: - enum OperationType { Undefined, PaintTileSet, PaintLayer, DeleteTexture }; + enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture }; QueuedOperation(OperationType type, TiledPage* page) : m_type(type) , m_page(page) {} virtual ~QueuedOperation() {} virtual void run() = 0; virtual bool operator==(const QueuedOperation* operation) = 0; + virtual int priority() { return -1; } OperationType type() const { return m_type; } TiledPage* page() const { return m_page; } private: @@ -65,6 +66,20 @@ class PageFilter : public OperationFilter { TiledPage* m_page; }; +class PagePaintFilter : public OperationFilter { + public: + PagePaintFilter(TiledPage* page) : m_page(page) {} + virtual bool check(QueuedOperation* operation) + { + if (operation->type() == QueuedOperation::PaintTile + && operation->page() == m_page) + return true; + return false; + } + private: + TiledPage* m_page; +}; + } #endif // QueuedOperation_h diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp index ad5de1f..e6bef6a 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -51,27 +51,11 @@ namespace WebCore { -void TexturesGenerator::scheduleOperation(QueuedOperation* operation, bool scheduleFirst) +void TexturesGenerator::scheduleOperation(QueuedOperation* operation) { { android::Mutex::Autolock lock(mRequestedOperationsLock); - for (unsigned int i = 0; i < mRequestedOperations.size(); i++) { - QueuedOperation** s = &mRequestedOperations[i]; - // A similar operation is already in the queue. The newer operation may - // have additional dirty tiles so delete the existing operation and - // replace it with the new one. - if (*s && *s == operation) { - QueuedOperation* oldOperation = *s; - *s = operation; - delete oldOperation; - return; - } - } - - if (scheduleFirst) - mRequestedOperations.prepend(operation); - else - mRequestedOperations.append(operation); + mRequestedOperations.append(operation); } mRequestedOperationsCond.signal(); } @@ -81,6 +65,11 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) removeOperationsForFilter(new PageFilter(page)); } +void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) +{ + removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); +} + void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer) { removeOperationsForFilter(new PaintLayerBaseFilter(layer)); @@ -93,6 +82,11 @@ void TexturesGenerator::removeOperationsForTexture(LayerTexture* texture) void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) { + removeOperationsForFilter(filter, true); +} + +void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) +{ android::Mutex::Autolock lock(mRequestedOperationsLock); for (unsigned int i = 0; i < mRequestedOperations.size();) { QueuedOperation* operation = mRequestedOperations[i]; @@ -104,18 +98,22 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) } } - QueuedOperation* operation = m_currentOperation; - if (operation && filter->check(operation)) - m_waitForCompletion = true; - - delete filter; - - // At this point, it means that we are currently executing an operation that - // we want to be removed -- we should wait until it is done, so that - // when we return our caller can be sure that there is no more operations - // in the queue matching the given filter. - while (m_waitForCompletion) - mRequestedOperationsCond.wait(mRequestedOperationsLock); + if (waitForRunning) { + QueuedOperation* operation = m_currentOperation; + if (operation && filter->check(operation)) + m_waitForCompletion = true; + + delete filter; + + // At this point, it means that we are currently executing an operation that + // we want to be removed -- we should wait until it is done, so that + // when we return our caller can be sure that there is no more operations + // in the queue matching the given filter. + while (m_waitForCompletion) + mRequestedOperationsCond.wait(mRequestedOperationsLock); + } else { + delete filter; + } } status_t TexturesGenerator::readyToRun() @@ -125,6 +123,37 @@ status_t TexturesGenerator::readyToRun() return NO_ERROR; } +// Must be called from within a lock! +QueuedOperation* TexturesGenerator::popNext() +{ + // Priority can change between when it was added and now + // Hence why the entire queue is rescanned + QueuedOperation* current = mRequestedOperations.last(); + int currentPriority = current->priority(); + if (currentPriority < 0) { + mRequestedOperations.removeLast(); + return current; + } + int currentIndex = mRequestedOperations.size() - 1; + // Scan from the back to make removing faster (less items to copy) + for (int i = mRequestedOperations.size() - 2; i >= 0; i--) { + QueuedOperation *next = mRequestedOperations[i]; + int nextPriority = next->priority(); + if (nextPriority < 0) { + // Found a very high priority item, go ahead and just handle it now + mRequestedOperations.remove(i); + return next; + } + if (nextPriority < currentPriority) { + current = next; + currentPriority = nextPriority; + currentIndex = i; + } + } + mRequestedOperations.remove(currentIndex); + return current; +} + bool TexturesGenerator::threadLoop() { // Check if we have any pending operations. @@ -138,20 +167,14 @@ bool TexturesGenerator::threadLoop() m_currentOperation = 0; bool stop = false; while (!stop) { - XLOG("threadLoop evaluating the requests"); mRequestedOperationsLock.lock(); - if (mRequestedOperations.size()) { - m_currentOperation = mRequestedOperations.first(); - mRequestedOperations.remove(0); - XLOG("threadLoop, popping the first request (%d requests left)", - mRequestedOperations.size()); - } + if (mRequestedOperations.size()) + m_currentOperation = popNext(); mRequestedOperationsLock.unlock(); if (m_currentOperation) { - XLOG("threadLoop, painting the request"); + XLOG("threadLoop, painting the request with priority %d", m_currentOperation->priority()); m_currentOperation->run(); - XLOG("threadLoop, painting the request - DONE"); } mRequestedOperationsLock.lock(); @@ -168,6 +191,7 @@ bool TexturesGenerator::threadLoop() mRequestedOperationsLock.unlock(); } + XLOG("threadLoop empty"); return true; } diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h index 169471c..b03f52d 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/WebCore/platform/graphics/android/TexturesGenerator.h @@ -30,7 +30,6 @@ #include "LayerTexture.h" #include "QueuedOperation.h" -#include "TileSet.h" #include "TiledPage.h" #include <utils/threads.h> @@ -52,11 +51,14 @@ public: void removeOperationsForPage(TiledPage* page); void removeOperationsForBaseLayer(BaseLayerAndroid* layer); void removeOperationsForTexture(LayerTexture* texture); + void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); void removeOperationsForFilter(OperationFilter* filter); + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); - void scheduleOperation(QueuedOperation* operation, bool scheduleFirst); + void scheduleOperation(QueuedOperation* operation); private: + QueuedOperation* popNext(); virtual bool threadLoop(); Vector<QueuedOperation*> mRequestedOperations; android::Mutex mRequestedOperationsLock; diff --git a/WebCore/platform/graphics/android/TileSet.h b/WebCore/platform/graphics/android/TileSet.h deleted file mode 100644 index aa0f2ed..0000000 --- a/WebCore/platform/graphics/android/TileSet.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2010, The Android Open Source Project - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TileSet_h -#define TileSet_h - -#if USE(ACCELERATED_COMPOSITING) - -#include "BaseTile.h" -#include "Vector.h" - -namespace WebCore { - -/** - * This purpose of this class is to act as a container for BaseTiles that need - * to upload their contents to the GPU. A TiledPage creates a new TileSet and - * provides the set with identifying characteristics of the TiledPage's current - * state (see constructor). This information allows the consumer of the TileSet - * to determine if an equivalent TileSet already exists in the upload pipeline. - */ -class TileSet { -public: - TileSet(TiledPage* tiledPage, int nbRows, int nbCols); - ~TileSet(); - - bool operator==(const TileSet& set); - void paint(); - - void add(BaseTile* texture) - { - m_tiles.append(texture); - } - - TiledPage* page() - { - return m_tiledPage; - } - - unsigned int size() - { - return m_tiles.size(); - } - -private: - Vector<BaseTile*> m_tiles; - - TiledPage* m_tiledPage; - int m_nbRows; - int m_nbCols; -}; - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) -#endif // TileSet_h diff --git a/WebCore/platform/graphics/android/TiledPage.cpp b/WebCore/platform/graphics/android/TiledPage.cpp index 21afe24..0251b03 100644 --- a/WebCore/platform/graphics/android/TiledPage.cpp +++ b/WebCore/platform/graphics/android/TiledPage.cpp @@ -30,7 +30,7 @@ #include "GLUtils.h" #include "IntRect.h" -#include "PaintTileSetOperation.h" +#include "PaintTileOperation.h" #include "TilesManager.h" #ifdef DEBUG @@ -82,7 +82,6 @@ void TiledPage::updateBaseTileSize() int baseTileSize = TilesManager::instance()->maxTextureCount() + 1; if (baseTileSize > m_baseTileSize) m_baseTileSize = baseTileSize; - XLOG("Allocate %d tiles", m_baseTileSize); } TiledPage::~TiledPage() @@ -126,6 +125,7 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC const int lastDirtyTileX = static_cast<int>(ceilf(inval.right() * invTileContentWidth)); const int lastDirtyTileY = static_cast<int>(ceilf(inval.bottom() * invTileContentHeight)); + XLOG("Marking X %d-%d and Y %d-%d dirty", firstDirtyTileX, lastDirtyTileX, firstDirtyTileY, lastDirtyTileY); // We defer marking the tile as dirty until the next time we need to prepare // to draw. m_invalRegion.op(firstDirtyTileX, firstDirtyTileY, lastDirtyTileX, lastDirtyTileY, SkRegion::kUnion_Op); @@ -133,12 +133,10 @@ void TiledPage::invalidateRect(const IntRect& inval, const unsigned int pictureC m_latestPictureInval = pictureCount; } -void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set) +void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds) { if (y < 0) return; - if (!set) - return; for (int i = 0; i < tilesInRow; i++) { int x = firstTileX; @@ -177,12 +175,41 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y // ensure there is a texture associated with the tile and then check to // see if the texture is dirty and in need of repainting currentTile->reserveTexture(); - if (currentTile->isDirty()) - set->add(currentTile); + updateTileUsedLevel(tileBounds, *currentTile); + if (currentTile->isDirty() && !currentTile->isRepaintPending()) { + PaintTileOperation *operation = new PaintTileOperation(currentTile); + TilesManager::instance()->scheduleOperation(operation); + } else if (currentTile->isDirty()) { + XLOG("Tile %dx%d is dirty, but awaiting repaint", currentTile->x(), currentTile->y()); + } } } } +void TiledPage::updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile) +{ + const int lastTileX = tileBounds.fRight - 1; + const int lastTileY = tileBounds.fBottom - 1; + + // set the used level of the tile (e.g. distance from the viewport) + int dx = 0; + int dy = 0; + + if (tileBounds.fLeft > tile.x()) + dx = tileBounds.fLeft - tile.x(); + else if (lastTileX < tile.x()) + dx = tile.x() - lastTileX; + + if (tileBounds.fTop > tile.y()) + dy = tileBounds.fTop - tile.y(); + else if (lastTileY < tile.y()) + dy = tile.y() - lastTileY; + + int d = std::max(dx, dy); + + tile.setUsedLevel(d); +} + void TiledPage::updateTileState(const SkIRect& tileBounds) { if (!m_glWebViewState || tileBounds.isEmpty()) { @@ -191,41 +218,19 @@ void TiledPage::updateTileState(const SkIRect& tileBounds) return; } - const int nbTilesWidth = tileBounds.width() - 1; - const int nbTilesHeight = tileBounds.height() - 1; - - const int lastTileX = tileBounds.fRight - 1; - const int lastTileY = tileBounds.fBottom - 1; - for (int x = 0; x < m_baseTileSize; x++) { BaseTile& tile = m_baseTiles[x]; - // if the tile is in the dirty region then we must invalidate it - if (m_invalRegion.contains(tile.x(), tile.y())) - tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); - // if the tile no longer has a texture then proceed to the next tile if (tile.isAvailable()) continue; - // set the used level of the tile (e.g. distance from the viewport) - int dx = 0; - int dy = 0; - - if (tileBounds.fLeft > tile.x()) - dx = tileBounds.fLeft - tile.x(); - else if (lastTileX < tile.x()) - dx = tile.x() - lastTileX; - - if (tileBounds.fTop > tile.y()) - dy = tileBounds.fTop - tile.y(); - else if (lastTileY < tile.y()) - dy = tile.y() - lastTileY; - - int d = std::max(dx, dy); + // if the tile is in the dirty region then we must invalidate it + if (m_invalRegion.contains(tile.x(), tile.y())) + tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); - tile.setUsedLevel(d); + updateTileUsedLevel(tileBounds, tile); } // clear the invalidated region as all tiles within that region have now @@ -234,8 +239,7 @@ void TiledPage::updateTileState(const SkIRect& tileBounds) m_invalTilesRegion.setEmpty(); } -void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, - bool scheduleFirst) +void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds) { if (!m_glWebViewState) return; @@ -243,6 +247,7 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound // update the tiles distance from the viewport updateTileState(tileBounds); m_prepare = true; + m_scrollingDown = goingDown; int firstTileX = tileBounds.fLeft; int firstTileY = tileBounds.fTop; @@ -255,43 +260,29 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound const int baseContentHeight = m_glWebViewState->baseContentHeight(); const int baseContentWidth = m_glWebViewState->baseContentWidth(); - TileSet* set = new TileSet(this, nbTilesHeight, nbTilesWidth); - - if (!scheduleFirst) { - // 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; - 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 + (nbTilesWidth * expandY * 2) <= nMaxTilesPerPage) { - firstTileY -= expandY; - lastTileY += expandY; - nbTilesHeight += expandY * 2; - } + // 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; + int expandX = TilesManager::instance()->expandedTileBoundsX(); + int expandY = TilesManager::instance()->expandedTileBoundsY(); + if (nTilesToPrepare + (nbTilesHeight * expandX * 2) <= nMaxTilesPerPage) { + firstTileX -= expandX; + lastTileX += expandX; + nbTilesWidth += expandX * 2; } - - // We chose to prepare tiles depending on the scroll direction. Tiles are - // appended to the list and the texture uploader goes through the list front - // to back. So we append tiles in reverse order because the last additions - // to the are processed first. - if (goingDown) { - for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, lastTileY - i, set); - } else { - for (int i = 0; i < nbTilesHeight; i++) - prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, set); + if (nTilesToPrepare + (nbTilesWidth * expandY * 2) <= nMaxTilesPerPage) { + firstTileY -= expandY; + lastTileY += expandY; + nbTilesHeight += expandY * 2; } + m_expandedTileBounds.fLeft = firstTileX; + m_expandedTileBounds.fTop = firstTileY; + m_expandedTileBounds.fRight = lastTileX; + m_expandedTileBounds.fBottom = lastTileY; - // The paint operation will take ownership of the tileSet here, so no delete - // is necessary. - PaintTileSetOperation* operation = new PaintTileSetOperation(set); - TilesManager::instance()->scheduleOperation(operation, scheduleFirst); + for (int i = 0; i < nbTilesHeight; i++) + prepareRow(goingLeft, nbTilesWidth, firstTileX, firstTileY + i, tileBounds); } bool TiledPage::ready(const SkIRect& tileBounds, float scale) @@ -330,7 +321,6 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds) 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 (actualTileBounds.contains(tile.x(), tile.y())) { @@ -344,11 +334,6 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds) tile.draw(transparency, rect); } } - -#ifdef DEBUG - XLOG("FINISHED WE DRAW %x (%.2f) with transparency %.2f", this, scale(), transparency); - TilesManager::instance()->printTextures(); -#endif // DEBUG } unsigned int TiledPage::paintBaseLayerContent(SkCanvas* canvas) diff --git a/WebCore/platform/graphics/android/TiledPage.h b/WebCore/platform/graphics/android/TiledPage.h index 7e0bb2e..1aa3e61 100644 --- a/WebCore/platform/graphics/android/TiledPage.h +++ b/WebCore/platform/graphics/android/TiledPage.h @@ -31,7 +31,6 @@ #include "BaseTile.h" #include "SkCanvas.h" #include "SkRegion.h" -#include "TileSet.h" namespace WebCore { @@ -57,8 +56,7 @@ public: TiledPage* sibling(); // prepare the page for display on the screen - void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, - bool scheduleFirst = false); + void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds); // check to see if the page is ready for display bool ready(const SkIRect& tileBounds, float scale); // draw the page on the screen @@ -75,10 +73,13 @@ public: void invalidateRect(const IntRect& invalRect, const unsigned int pictureCount); void setUsable(bool usable); void updateBaseTileSize(); + bool scrollingDown() { return m_scrollingDown; } + SkIRect* expandedTileBounds() { return &m_expandedTileBounds; } private: void updateTileState(const SkIRect& tileBounds); - void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, TileSet* set); + void prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y, const SkIRect& tileBounds); + void updateTileUsedLevel(const SkIRect& tileBounds, BaseTile& tile); BaseTile* getBaseTile(int x, int y) const; @@ -103,6 +104,8 @@ private: SkRegion m_invalTilesRegion; unsigned int m_latestPictureInval; bool m_prepare; + bool m_scrollingDown; + SkIRect m_expandedTileBounds; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index 5a4e28a..6d49cca 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -39,8 +39,6 @@ namespace WebCore { -class TileSet; - class TilesManager { public: static TilesManager* instance(); @@ -57,6 +55,11 @@ public: m_pixmapsGenerationThread->removeOperationsForPage(page); } + void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) + { + m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); + } + void removeOperationsForBaseLayer(BaseLayerAndroid* layer) { m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer); @@ -67,9 +70,9 @@ public: m_pixmapsGenerationThread->removeOperationsForTexture(texture); } - void scheduleOperation(QueuedOperation* operation, bool scheduleFirst = false) + void scheduleOperation(QueuedOperation* operation) { - m_pixmapsGenerationThread->scheduleOperation(operation, scheduleFirst); + m_pixmapsGenerationThread->scheduleOperation(operation); } ShaderProgram* shader() { return &m_shader; } |