diff options
author | Chris Craik <ccraik@google.com> | 2012-02-15 13:26:22 -0800 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2012-02-16 13:26:20 -0800 |
commit | 92a7e4bc6b67b150cbb30f78374173ecfeb43607 (patch) | |
tree | cee0719ef12e63b17ad4711b7e4bd79d5a82669c /Source/WebCore/platform/graphics/android | |
parent | 3410ffc0890f04ba9ca38573ab37c309b4aff5bd (diff) | |
download | external_webkit-92a7e4bc6b67b150cbb30f78374173ecfeb43607.zip external_webkit-92a7e4bc6b67b150cbb30f78374173ecfeb43607.tar.gz external_webkit-92a7e4bc6b67b150cbb30f78374173ecfeb43607.tar.bz2 |
simplify texture generation filters
Filters can no longer block, which removes the need for transfer queue
interruption. The filter no longer touches the currently painting tile.
Tiles are now all ref-counted to accomodate the container being deleted while
one of its tiles is still painting.
Change-Id: Iaa4848665efdf90846defb0a53bf1ea013b8421b
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
12 files changed, 94 insertions, 115 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index a3c92cd..2d2867c 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -247,7 +247,7 @@ bool BaseLayerAndroid::prepareBasePictureInGL(SkRect& viewport, float scale, nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, TiledPage::VisibleBounds); // Cancel pending paints for the foreground page - TilesManager::instance()->removePaintOperationsForPage(tiledPage, false); + TilesManager::instance()->removePaintOperationsForPage(tiledPage); } // If we fired a request, let's check if it's ready to use diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h index 5434dbf..25d234b 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/TextureOwner.h @@ -26,6 +26,8 @@ #ifndef TextureOwner_h #define TextureOwner_h +#include "SkRefCnt.h" + class SkCanvas; class Layer; @@ -35,7 +37,7 @@ class TiledPage; class BaseTileTexture; class GLWebViewState; -class TextureOwner { +class TextureOwner : public SkRefCnt { public: virtual ~TextureOwner() { } virtual bool removeTexture(BaseTileTexture* texture) = 0; diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp index bccb99b..d27631b 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -65,18 +65,13 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page) removeOperationsForFilter(new PageFilter(page)); } -void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitForRunning) +void TexturesGenerator::removePaintOperationsForPage(TiledPage* page) { - removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); + removeOperationsForFilter(new PagePaintFilter(page)); } void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) { - removeOperationsForFilter(filter, true); -} - -void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) -{ if (!filter) return; @@ -90,34 +85,7 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool i++; } } - - if (waitForRunning && m_currentOperation) { - QueuedOperation* operation = m_currentOperation; - - if (operation && filter->check(operation)) { - m_waitForCompletion = true; - // The reason we are signaling the transferQueue is : - // TransferQueue may be waiting a slot to work on, but now UI - // thread is waiting for Tex Gen thread to finish first before the - // UI thread can free a slot for the transferQueue. - // Therefore, it could be a deadlock. - // The solution is use this as a flag to tell Tex Gen thread that - // UI thread is waiting now, Tex Gen thread should not wait for the - // queue any more. - TilesManager::instance()->transferQueue()->interruptTransferQueue(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; - } + delete filter; } status_t TexturesGenerator::readyToRun() @@ -192,7 +160,6 @@ bool TexturesGenerator::threadLoop() stop = true; if (m_waitForCompletion) { m_waitForCompletion = false; - TilesManager::instance()->transferQueue()->interruptTransferQueue(false); mRequestedOperationsCond.signal(); } mRequestedOperationsLock.unlock(); diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h index 2e3b6b4..c7924cc 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.h @@ -42,16 +42,18 @@ class LayerAndroid; class TexturesGenerator : public Thread { public: - TexturesGenerator() : Thread(false) + TexturesGenerator() + : Thread(false) , m_waitForCompletion(false) - , m_currentOperation(0) { } + , m_currentOperation(0) + {} + virtual ~TexturesGenerator() { } virtual status_t readyToRun(); void removeOperationsForPage(TiledPage* page); - void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); + void removePaintOperationsForPage(TiledPage* page); void removeOperationsForFilter(OperationFilter* filter); - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); void scheduleOperation(QueuedOperation* operation); diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 8c43fc4..80d2c3f 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -59,8 +59,7 @@ namespace WebCore { using namespace android; TiledPage::TiledPage(int id, GLWebViewState* state) - : m_baseTiles(0) - , m_baseTileSize(0) + : m_baseTileSize(0) , m_id(id) , m_scale(1) , m_invScale(1) @@ -70,7 +69,11 @@ TiledPage::TiledPage(int id, GLWebViewState* state) , m_isPrefetchPage(false) , m_willDraw(false) { - m_baseTiles = new BaseTile[TilesManager::getMaxTextureAllocation() + 1]; + int maxTiles = TilesManager::getMaxTextureAllocation() + 1; + m_baseTiles = new BaseTile*[maxTiles]; + for (int i = 0; i < maxTiles; i++) + m_baseTiles[i] = new BaseTile(); + #ifdef DEBUG_COUNT ClassTracker::instance()->increment("TiledPage"); #endif @@ -94,13 +97,14 @@ void TiledPage::updateBaseTileSize() TiledPage::~TiledPage() { TilesManager* tilesManager = TilesManager::instance(); - // In order to delete the page we must ensure that none of its BaseTiles are - // currently painting or scheduled to be painted by the TextureGenerator + // remove as many painting operations for this page as possible, to avoid + // unnecessary work. tilesManager->removeOperationsForPage(this); - // Discard the transfer queue after the removal operation to make sure - // no tiles for this page will be left in the transfer queue. - tilesManager->transferQueue()->setPendingDiscardWithLock(); - delete[] m_baseTiles; + + int maxTiles = TilesManager::getMaxTextureAllocation() + 1; + for (int i = 0; i < maxTiles; i++) + SkSafeUnref(m_baseTiles[i]); + delete m_baseTiles; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledPage"); #endif @@ -110,9 +114,9 @@ BaseTile* TiledPage::getBaseTile(int x, int y) const { // TODO: replace loop over array with HashMap indexing for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) - return &tile; + BaseTile* tile = m_baseTiles[j]; + if (tile->x() == x && tile->y() == y) + return tile; } return 0; } @@ -120,8 +124,8 @@ BaseTile* TiledPage::getBaseTile(int x, int y) const void TiledPage::discardTextures() { for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - tile.discardTextures(); + BaseTile* tile = m_baseTiles[j]; + tile->discardTextures(); } return; } @@ -161,14 +165,14 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y BaseTile* currentTile = 0; BaseTile* availableTile = 0; for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.x() == x && tile.y() == y) { - currentTile = &tile; + BaseTile* tile = m_baseTiles[j]; + if (tile->x() == x && tile->y() == y) { + currentTile = tile; break; } - if (!availableTile || (tile.drawCount() < availableTile->drawCount())) - availableTile = &tile; + if (!availableTile || (tile->drawCount() < availableTile->drawCount())) + availableTile = tile; } if (!currentTile && availableTile) { @@ -216,12 +220,12 @@ bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds) bool visibleTileIsDirty = false; for (int x = 0; x < m_baseTileSize; x++) { - BaseTile& tile = m_baseTiles[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 (tileBounds.contains(tile.x(), tile.y())) + if (m_invalRegion.contains(tile->x(), tile->y())) { + tile->markAsDirty(m_latestPictureInval, m_invalTilesRegion); + if (tileBounds.contains(tile->x(), tile->y())) visibleTileIsDirty = true; } } @@ -301,9 +305,9 @@ bool TiledPage::hasMissingContent(const SkIRect& tileBounds) { int neededTiles = tileBounds.width() * tileBounds.height(); for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.frontTexture()) + BaseTile* tile = m_baseTiles[j]; + if (tileBounds.contains(tile->x(), tile->y())) { + if (tile->frontTexture()) neededTiles--; } } @@ -315,9 +319,9 @@ bool TiledPage::isReady(const SkIRect& tileBounds) int neededTiles = tileBounds.width() * tileBounds.height(); XLOG("tiled page %p needs %d ready tiles", this, neededTiles); for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tileBounds.contains(tile.x(), tile.y())) { - if (tile.isTileReady()) + BaseTile* tile = m_baseTiles[j]; + if (tileBounds.contains(tile->x(), tile->y())) { + if (tile->isTileReady()) neededTiles--; } } @@ -348,8 +352,8 @@ bool TiledPage::swapBuffersIfReady(const SkIRect& tileBounds, float scale) // swap every tile on page (even if off screen) for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - if (tile.swapTexturesIfNeeded()) + BaseTile* tile = m_baseTiles[j]; + if (tile->swapTexturesIfNeeded()) swaps++; } @@ -373,16 +377,16 @@ void TiledPage::drawGL() const float tileHeight = TilesManager::tileHeight() * m_invScale; for (int j = 0; j < m_baseTileSize; j++) { - BaseTile& tile = m_baseTiles[j]; - bool tileInView = m_tileBounds.contains(tile.x(), tile.y()); + BaseTile* tile = m_baseTiles[j]; + bool tileInView = m_tileBounds.contains(tile->x(), tile->y()); if (tileInView) { SkRect rect; - rect.fLeft = tile.x() * tileWidth; - rect.fTop = tile.y() * tileHeight; + rect.fLeft = tile->x() * tileWidth; + rect.fTop = tile->y() * tileHeight; rect.fRight = rect.fLeft + tileWidth; rect.fBottom = rect.fTop + tileHeight; - tile.draw(m_transparency, rect, m_scale); + tile->draw(m_transparency, rect, m_scale); } TilesManager::instance()->getProfiler()->nextTile(tile, m_invScale, tileInView); diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index 791e1f6..d858cc2 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -105,9 +105,10 @@ private: BaseTile* getBaseTile(int x, int y) const; - // array of tiles used to compose a page. The tiles are allocated in the + // array of tile ptrs used to compose a page. The tiles are allocated in the // constructor to prevent them from potentially being allocated on the stack - BaseTile* m_baseTiles; + BaseTile** m_baseTiles; + // stores the number of tiles in the m_baseTiles array. This enables us to // quickly iterate over the array without have to check it's size int m_baseTileSize; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index 1e8b946..4b872a3 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -317,9 +317,8 @@ const TransformationMatrix* TiledTexture::transform() void TiledTexture::removeTiles() { - for (unsigned int i = 0; i < m_tiles.size(); i++) { - delete m_tiles[i]; - } + for (unsigned int i = 0; i < m_tiles.size(); i++) + SkSafeUnref(m_tiles[i]); m_tiles.clear(); } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index b670055..d3852d9 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -58,9 +58,9 @@ public: return gInstance != 0; } - void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false) + void removeOperationsForFilter(OperationFilter* filter) { - m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); + m_pixmapsGenerationThread->removeOperationsForFilter(filter); } void removeOperationsForPage(TiledPage* page) @@ -68,9 +68,9 @@ public: m_pixmapsGenerationThread->removeOperationsForPage(page); } - void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) + void removePaintOperationsForPage(TiledPage* page) { - m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); + m_pixmapsGenerationThread->removePaintOperationsForPage(page); } void scheduleOperation(QueuedOperation* operation) diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp index 0271ee3..d422904 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.cpp +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.cpp @@ -103,14 +103,14 @@ void TilesProfiler::nextFrame(int left, int top, int right, int bottom, float sc scale, true, (int)(timeDelta * 1000))); } -void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) +void TilesProfiler::nextTile(BaseTile* tile, float scale, bool inView) { if (!m_enabled || (m_records.size() > MAX_PROF_FRAMES) || (m_records.size() == 0)) return; - bool isReady = tile.isTileReady(); - int left = tile.x() * TilesManager::tileWidth(); - int top = tile.y() * TilesManager::tileWidth(); + bool isReady = tile->isTileReady(); + int left = tile->x() * TilesManager::tileWidth(); + int top = tile->y() * TilesManager::tileWidth(); int right = left + TilesManager::tileWidth(); int bottom = top + TilesManager::tileWidth(); @@ -122,7 +122,7 @@ void TilesProfiler::nextTile(BaseTile& tile, float scale, bool inView) } m_records.last().append(TileProfileRecord( left, top, right, bottom, - scale, isReady, (int)tile.drawCount())); + scale, isReady, (int)tile->drawCount())); XLOG("adding tile %d %d %d %d, scale %f", left, top, right, bottom, scale); } diff --git a/Source/WebCore/platform/graphics/android/TilesProfiler.h b/Source/WebCore/platform/graphics/android/TilesProfiler.h index 286d350..7a3fe59 100644 --- a/Source/WebCore/platform/graphics/android/TilesProfiler.h +++ b/Source/WebCore/platform/graphics/android/TilesProfiler.h @@ -58,7 +58,7 @@ public: float stop(); void clear(); void nextFrame(int left, int top, int right, int bottom, float scale); - void nextTile(BaseTile& tile, float scale, bool inView); + void nextTile(BaseTile* tile, float scale, bool inView); void nextInval(const IntRect& rect, float scale); int numFrames() { return m_records.size(); diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 2d5be64..3c2ed1b 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -67,7 +67,6 @@ TransferQueue::TransferQueue(bool useMinimalMem) , m_fboID(0) , m_sharedSurfaceTextureId(0) , m_hasGLContext(true) - , m_interruptedByRemovingOp(false) , m_currentDisplay(EGL_NO_DISPLAY) , m_currentUploadType(DEFAULT_UPLOAD_TYPE) { @@ -246,17 +245,8 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, #endif } -void TransferQueue::interruptTransferQueue(bool interrupt) -{ - m_transferQueueItemLocks.lock(); - m_interruptedByRemovingOp = interrupt; - if (m_interruptedByRemovingOp) - m_transferQueueItemCond.signal(); - m_transferQueueItemLocks.unlock(); -} - // This function must be called inside the m_transferQueueItemLocks, for the -// wait, m_interruptedByRemovingOp and getHasGLContext(). +// wait and getHasGLContext(). // Only called by updateQueueWithBitmap() for now. bool TransferQueue::readyForUpdate() { @@ -264,13 +254,8 @@ bool TransferQueue::readyForUpdate() return false; // Don't use a while loop since when the WebView tear down, the emptyCount // will still be 0, and we bailed out b/c of GL context lost. - if (!m_emptyItemCount) { - if (m_interruptedByRemovingOp) - return false; + if (!m_emptyItemCount) m_transferQueueItemCond.wait(m_transferQueueItemLocks); - if (m_interruptedByRemovingOp) - return false; - } if (!getHasGLContext()) return false; @@ -330,6 +315,8 @@ void TransferQueue::setPendingDiscard() if (m_transferQueue[i].status == pendingBlit) m_transferQueue[i].status = pendingDiscard; + for (unsigned int i = 0 ; i < m_pureColorTileQueue.size(); i++) + SkSafeUnref(m_pureColorTileQueue[i].savedBaseTilePtr); m_pureColorTileQueue.clear(); bool GLContextExisted = getHasGLContext(); @@ -358,6 +345,7 @@ void TransferQueue::updatePureColorTiles() // The queue should be clear instead of setting to different status. XLOG("Warning: Don't expect an emptyItem here."); } + SkSafeUnref(data->savedBaseTilePtr); } m_pureColorTileQueue.clear(); } @@ -398,6 +386,11 @@ void TransferQueue::updateDirtyBaseTiles() if (result != OK) XLOGC("unexpected error: updateTexImage return %d", result); } + + XLOG("removing tile %p from %p, update", + m_transferQueue[index].savedBaseTilePtr, + &m_transferQueue[index]); + SkSafeUnref(m_transferQueue[index].savedBaseTilePtr); m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { @@ -518,7 +511,7 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, ANativeWindow_unlockAndPost(m_ANW.get()); } - // b) After update the Surface Texture, now udpate the transfer queue info. + // b) After update the Surface Texture, now update the transfer queue info. addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); XLOG("Bitmap updated x, y %d %d, baseTile %p", @@ -543,8 +536,19 @@ void TransferQueue::addItemCommon(const TileRenderInfo* renderInfo, TextureUploadType type, TileTransferData* data) { + BaseTile* old = data->savedBaseTilePtr; + SkSafeRef(renderInfo->baseTile); + SkSafeUnref(data->savedBaseTilePtr); + data->savedBaseTileTexturePtr = renderInfo->baseTile->backTexture(); data->savedBaseTilePtr = renderInfo->baseTile; + XLOG("adding tile %p, %d by %d, refs %d, removed %p, dataPtr %p", + data->savedBaseTilePtr, + data->savedBaseTilePtr->x(), + data->savedBaseTilePtr->y(), + data->savedBaseTilePtr->getRefCnt(), + old, + data); data->status = pendingBlit; data->uploadType = type; @@ -638,6 +642,10 @@ void TransferQueue::cleanupPendingDiscard() XLOG("transfer queue discarded tile %p, removed texture", tile); } + XLOG("removing tile %p from %p, cleanup", + m_transferQueue[index].savedBaseTilePtr, + &m_transferQueue[index]); + SkSafeUnref(m_transferQueue[index].savedBaseTilePtr); m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].savedBaseTileTexturePtr = 0; m_transferQueue[index].status = emptyItem; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index 5dd2e0a..30dd0c6 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -129,8 +129,6 @@ public: // The lock will be done when returning true. bool readyForUpdate(); - void interruptTransferQueue(bool); - void lockQueue() { m_transferQueueItemLocks.lock(); } void unlockQueue() { m_transferQueueItemLocks.unlock(); } @@ -196,8 +194,6 @@ private: int m_emptyItemCount; - bool m_interruptedByRemovingOp; - // We are using wait/signal to handle our own queue sync. // First of all, if we don't have our own lock, then while WebView is // destroyed, the UI thread will wait for the Tex Gen to get out from |