diff options
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 |