diff options
9 files changed, 96 insertions, 33 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index b3a6b84..04d0fc9 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -59,9 +59,6 @@ BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) m_size.set(w, h); m_ownTextureId = 0; - // Make sure they are created on the UI thread. - TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h); - #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTileTexture"); #endif diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index d8ad1c5..b701169 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -92,7 +92,6 @@ GLWebViewState::GLWebViewState() , m_goingLeft(false) , m_expandedTileBoundsX(0) , m_expandedTileBoundsY(0) - , m_highEndGfx(false) , m_scale(1) , m_layersRenderingMode(kAllTextures) { @@ -276,10 +275,11 @@ void GLWebViewState::setViewport(SkRect& viewport, float scale) int viewMaxTileX = static_cast<int>(ceilf((viewport.width()-1) * invTileContentWidth)) + 1; int viewMaxTileY = static_cast<int>(ceilf((viewport.height()-1) * invTileContentHeight)) + 1; + TilesManager* manager = TilesManager::instance(); int maxTextureCount = (viewMaxTileX + m_expandedTileBoundsX * 2) * - (viewMaxTileY + m_expandedTileBoundsY * 2) * (m_highEndGfx ? 4 : 2); + (viewMaxTileY + m_expandedTileBoundsY * 2) * (manager->highEndGfx() ? 4 : 2); - TilesManager::instance()->setMaxTextureCount(maxTextureCount); + manager->setMaxTextureCount(maxTextureCount); m_tiledPageA->updateBaseTileSize(); m_tiledPageB->updateBaseTileSize(); } @@ -350,11 +350,18 @@ double GLWebViewState::setupDrawing(IntRect& viewRect, SkRect& visibleRect, int width = viewRect.width(); int height = viewRect.height(); + // Make sure GL resources are created on the UI thread. ShaderProgram* shader = TilesManager::instance()->shader(); if (shader->needsInit()) { XLOG("Reinit shader"); shader->init(); } + TransferQueue* transferQueue = TilesManager::instance()->transferQueue(); + if (transferQueue->needsInit()) { + transferQueue->initGLResources(TilesManager::tileWidth(), + TilesManager::tileHeight()); + } + shader->setViewport(visibleRect, scale); shader->setViewRect(viewRect); shader->setWebViewRect(webViewRect); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index d195597..169e276 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -234,7 +234,6 @@ public: int expandedTileBoundsX() { return m_expandedTileBoundsX; } int expandedTileBoundsY() { return m_expandedTileBoundsY; } - void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; } float scale() { return m_scale; } @@ -289,7 +288,6 @@ private: int m_expandedTileBoundsX; int m_expandedTileBoundsY; - bool m_highEndGfx; float m_scale; diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 136b5a7..8c43fc4 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -99,7 +99,7 @@ TiledPage::~TiledPage() 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()->discardQueue(); + tilesManager->transferQueue()->setPendingDiscardWithLock(); delete[] m_baseTiles; #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("TiledPage"); diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index cbbbe5c..082f0bc 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -96,6 +96,7 @@ int TilesManager::getMaxTextureAllocation() TilesManager::TilesManager() : m_layerTexturesRemain(true) + , m_highEndGfx(false) , m_maxTextureCount(0) , m_maxLayerTextureCount(0) , m_generatorReady(false) @@ -356,6 +357,16 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } +void TilesManager::setHighEndGfx(bool highEnd) +{ + m_highEndGfx = highEnd; +} + +bool TilesManager::highEndGfx() +{ + return m_highEndGfx; +} + int TilesManager::maxTextureCount() { android::Mutex::Autolock lock(m_texturesLock); diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index dd01fc5..855994d 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -106,6 +106,10 @@ public: void resetTextureUsage(TiledPage* page); + // m_highEndGfx is written/read only on UI thread, no need for a lock. + void setHighEndGfx(bool highEnd); + bool highEndGfx(); + int maxTextureCount(); int maxLayerTextureCount(); void setMaxTextureCount(int max); @@ -226,6 +230,7 @@ private: Vector<PaintedSurface*> m_paintedSurfaces; + bool m_highEndGfx; int m_maxTextureCount; int m_maxLayerTextureCount; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 5d47629..56d79a1 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -77,16 +77,32 @@ TransferQueue::TransferQueue() TransferQueue::~TransferQueue() { - glDeleteFramebuffers(1, &m_fboID); - m_fboID = 0; - glDeleteTextures(1, &m_sharedSurfaceTextureId); - m_sharedSurfaceTextureId = 0; - + android::Mutex::Autolock lock(m_transferQueueItemLocks); + cleanupGLResources(); delete[] m_transferQueue; } -void TransferQueue::initSharedSurfaceTextures(int width, int height) +// This should be called within the m_transferQueueItemLocks. +// Now only called by emptyQueue() and destructor. +void TransferQueue::cleanupGLResources() { + if (m_sharedSurfaceTexture.get()) { + m_sharedSurfaceTexture->abandon(); + m_sharedSurfaceTexture.clear(); + } + if (m_fboID) { + glDeleteFramebuffers(1, &m_fboID); + m_fboID = 0; + } + if (m_sharedSurfaceTextureId) { + glDeleteTextures(1, &m_sharedSurfaceTextureId); + m_sharedSurfaceTextureId = 0; + } +} + +void TransferQueue::initGLResources(int width, int height) +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); if (!m_sharedSurfaceTextureId) { glGenTextures(1, &m_sharedSurfaceTextureId); m_sharedSurfaceTexture = @@ -260,11 +276,27 @@ void TransferQueue::setHasGLContext(bool hasContext) m_hasGLContext = hasContext; } -// Only called when WebView is destroyed or switching the uploadType. -void TransferQueue::discardQueue() +void TransferQueue::setPendingDiscardWithLock() +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); +} + +void TransferQueue::emptyQueue() { android::Mutex::Autolock lock(m_transferQueueItemLocks); + setPendingDiscard(); + cleanupPendingDiscard(); + cleanupGLResources(); +} +// Set all the content in the queue to pendingDiscard, after this, there will +// be nothing added to the queue, and this can be called in any thread. +// However, in order to discard the content in the Surface Texture using +// updateTexImage, cleanupPendingDiscard need to be called on the UI thread. +// Must be called within a m_transferQueueItemLocks. +void TransferQueue::setPendingDiscard() +{ for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) if (m_transferQueue[i].status == pendingBlit) m_transferQueue[i].status = pendingDiscard; @@ -306,7 +338,7 @@ void TransferQueue::updateDirtyBaseTiles() { android::Mutex::Autolock lock(m_transferQueueItemLocks); - cleanupTransportQueue(); + cleanupPendingDiscard(); if (!getHasGLContext()) setHasGLContext(true); @@ -402,10 +434,13 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap) { - m_transferQueueItemLocks.lock(); + // This lock need to cover the full update since it is possible that queue + // will be cleaned up in the middle of this update without the lock. + // The Surface Texture will not block us since the readyForUpdate will check + // availability of the slots in the queue first. + android::Mutex::Autolock lock(m_transferQueueItemLocks); bool ready = readyForUpdate(); TextureUploadType currentUploadType = m_currentUploadType; - m_transferQueueItemLocks.unlock(); if (!ready) { XLOG("Quit bitmap update: not ready! for tile x y %d %d", renderInfo->x, renderInfo->y); @@ -449,11 +484,9 @@ bool TransferQueue::tryUpdateQueueWithBitmap(const TileRenderInfo* renderInfo, ANativeWindow_unlockAndPost(m_ANW.get()); } - m_transferQueueItemLocks.lock(); // b) After update the Surface Texture, now udpate the transfer queue info. addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); - m_transferQueueItemLocks.unlock(); XLOG("Bitmap updated x, y %d %d, baseTile %p", renderInfo->x, renderInfo->y, renderInfo->baseTile); return true; @@ -524,19 +557,19 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, void TransferQueue::setTextureUploadType(TextureUploadType type) { + android::Mutex::Autolock lock(m_transferQueueItemLocks); if (m_currentUploadType == type) return; - discardQueue(); + setPendingDiscard(); - android::Mutex::Autolock lock(m_transferQueueItemLocks); m_currentUploadType = type; XLOGC("Now we set the upload to %s", m_currentUploadType == GpuUpload ? "GpuUpload" : "CpuUpload"); } -// Note: this need to be called within th lock. -// Only called by updateDirtyBaseTiles() for now -void TransferQueue::cleanupTransportQueue() +// Note: this need to be called within the lock and on the UI thread. +// Only called by updateDirtyBaseTiles() and emptyQueue() for now +void TransferQueue::cleanupPendingDiscard() { int index = getNextTransferQueueIndex(); diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index 629935f..a18d448 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -113,17 +113,15 @@ public: // This will be called by the browser through nativeSetProperty void setTextureUploadType(TextureUploadType type); - + void cleanupGLResources(); void updateDirtyBaseTiles(); - void initSharedSurfaceTextures(int width, int height); + void initGLResources(int width, int height); // insert the bitmap into the queue, mark the tile dirty if failing void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap); - void discardQueue(); - void addItemInTransferQueue(const TileRenderInfo* info, TextureUploadType type, const SkBitmap* bitmap); @@ -138,6 +136,10 @@ public: void addItemInPureColorQueue(const TileRenderInfo* renderInfo, Color color); + void setPendingDiscardWithLock(); + void emptyQueue(); + + bool needsInit() { return !m_sharedSurfaceTextureId; } // This queue can be accessed from UI and TexGen thread, therefore, we need // a lock to protect its access TileTransferData* m_transferQueue; @@ -164,9 +166,10 @@ private: // Check the current transfer queue item is obsolete or not. bool checkObsolete(const TileTransferData* data); + void setPendingDiscard(); // Before each draw call and the blit operation, clean up all the // pendingDiscard items. - void cleanupTransportQueue(); + void cleanupPendingDiscard(); void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, GLuint srcTexId, GLenum srcTexTarget, diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 78881a9..6c49bb7 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -450,8 +450,9 @@ bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, return false; if (!m_glWebViewState) { + TilesManager::instance()->setHighEndGfx(m_isHighEndGfx); + m_glWebViewState = new GLWebViewState(); - m_glWebViewState->setHighEndGfx(m_isHighEndGfx); m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring); m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage); if (m_baseLayer->content()) { @@ -2640,6 +2641,14 @@ static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey) static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) { if (TilesManager::hardwareAccelerationEnabled()) { + // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should + // make sure the transfer queue is empty and then abandon the Surface + // Texture to avoid ANR b/c framework may destroy the EGL context. + // Refer to WindowManagerImpl.java for conditions we followed. + if (level >= TRIM_MEMORY_MODERATE + && !TilesManager::instance()->highEndGfx()) + TilesManager::instance()->transferQueue()->emptyQueue(); + bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; TilesManager::instance()->discardTextures(freeAllTextures, glTextures); } |