diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2011-08-03 17:40:49 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-08-03 17:40:49 -0700 |
commit | 9c20fe3057959d107a9b9f8ee78f2d244313fe77 (patch) | |
tree | c101172b711e61c20bd613169896c962e13793f0 /Source/WebCore/platform | |
parent | ef238925ea0ba6305e4540aff5c6953503993f3b (diff) | |
parent | 51c84083c0059a8e849bf0031704b0ec402059f0 (diff) | |
download | external_webkit-9c20fe3057959d107a9b9f8ee78f2d244313fe77.zip external_webkit-9c20fe3057959d107a9b9f8ee78f2d244313fe77.tar.gz external_webkit-9c20fe3057959d107a9b9f8ee78f2d244313fe77.tar.bz2 |
Merge "Finalize the sync part."
Diffstat (limited to 'Source/WebCore/platform')
5 files changed, 134 insertions, 192 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 8bc560e..60c1ebb 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -92,17 +92,6 @@ BaseTile::BaseTile(bool isLayerTile) BaseTile::~BaseTile() { - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - if (tileQueue->getHasGLContext()) { - tileQueue->m_transferQueueLock.lock(); - for (int i = 0 ; i < tileQueue->size(); i ++) { - TileTransferData* data = &(tileQueue->m_transferQueue[i]); - if (data->savedBaseTilePtr == this) - data->status = pendingDiscard; - } - tileQueue->m_transferQueueLock.unlock(); - } - setUsedLevel(-1); if (m_texture) m_texture->release(this); diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index d39b05b..039896e 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -488,69 +488,8 @@ void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderI || !renderInfo->textureInfo || !renderInfo->baseTile) return; - TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); - // Only changed in the Tex Gen thread. - const int index = tileQueue->getNextTransferQueueIndex(); - bool ready = tileQueue->lockForUpdate(index, renderInfo); - if (!ready) - return; - - // Dequeue the Surface Texture. - sp<ANativeWindow> ANW = tileQueue->m_ANW; - if (!ANW.get()) { - XLOG("ERROR: ANW is null"); - return; - } - ANativeWindowBuffer* anb; - - // We bound the Surface Texture update and transfer queue update together. - tileQueue->m_transferQueueLock.lock(); - - int status = ANW->dequeueBuffer(ANW.get(), &anb); - checkSurfaceTextureError("dequeueBuffer", status); - // a) Update surface texture - sp<android::GraphicBuffer> buf(new android::GraphicBuffer(anb, false)); - status |= ANW->lockBuffer(ANW.get(), buf->getNativeBuffer()); // Mutex Lock - checkSurfaceTextureError("lockBuffer", status); - - // Fill the buffer with the content of the bitmap - uint8_t* img = 0; - status |= buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); - checkSurfaceTextureError("lock", status); - - if (status == NO_ERROR) { - int row, col; - int bpp = 4; // Now we only deal with RGBA8888 format. - int width = TilesManager::instance()->tileWidth(); - int height = TilesManager::instance()->tileHeight(); - if (x == 0 && y == 0 && bitmap.width() == width && bitmap.height() == height) { - bitmap.lockPixels(); - uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); - // Copied line by line since we need to handle the offsets and stride. - for (row = 0 ; row < bitmap.height(); row ++) { - uint8_t* dst = &(img[(buf->getStride() * (row + x) + y) * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - bitmap.unlockPixels(); - } - else{ - // TODO: implement the partial invalidate here! - XLOG("ERROR: don't expect to get here yet before we support partial inval"); - } - } - buf->unlock(); - - status = ANW->queueBuffer(ANW.get(), buf->getNativeBuffer()); - checkSurfaceTextureError("queueBuffer", status); - - // b) After update the Surface Texture, now udpate the transfer queue info. - tileQueue->addItemInTransferQueue(renderInfo, index); - XLOG("Bitmap updated x, y %d %d, baseTile %p", - renderInfo->x, renderInfo->y, renderInfo->baseTile); - - tileQueue->m_transferQueueLock.unlock(); + TilesManager::instance()->transferQueue()->updateQueueWithBitmap(renderInfo, x, y, bitmap); } void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 7b1581b..9a18758 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -204,9 +204,7 @@ void TilesManager::cleanupTilesTextures() m_paintedSurfaces.remove(m_paintedSurfaces.find(collect[i])); TilePainter* painter = collect[i]->texture(); // Mark the current painter to destroy!! - transferQueue()->m_currentRemovingPaint = painter; m_pixmapsGenerationThread->removeOperationsForPainter(painter, true); - transferQueue()->m_currentRemovingPaint = 0; XLOG("destroy %x (%x)", collect[i], painter); delete collect[i]; } diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index 878affb..0d48175 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -53,15 +53,14 @@ namespace WebCore { TransferQueue::TransferQueue() - : m_currentRemovingPaint(0) - , m_transferQueueIndex(0) + : m_transferQueueIndex(0) , m_fboID(0) , m_sharedSurfaceTextureId(0) , m_hasGLContext(true) { memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit)); - m_transferQueueItemLocks = new android::Mutex[ST_BUFFER_NUMBER]; + m_emptyItemCount = ST_BUFFER_NUMBER; m_transferQueue = new TileTransferData[ST_BUFFER_NUMBER]; for (int i = 0; i < ST_BUFFER_NUMBER; i++) { @@ -77,15 +76,9 @@ TransferQueue::~TransferQueue() glDeleteTextures(1, &m_sharedSurfaceTextureId); m_sharedSurfaceTextureId = 0; - delete[] m_transferQueueItemLocks; delete[] m_transferQueue; } -int TransferQueue::size() -{ - return ST_BUFFER_NUMBER; -} - void TransferQueue::initSharedSurfaceTextures(int width, int height) { if (!m_sharedSurfaceTextureId) { @@ -170,77 +163,55 @@ void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, GL GLUtils::checkGlError("copy the surface texture into the normal one"); } -bool TransferQueue::currentOpWaitingRemoval(const TileRenderInfo* renderInfo) +bool TransferQueue::readyForUpdate() { - if (m_currentRemovingPaint - && m_currentRemovingPaint == renderInfo->tilePainter) - return true; - return false; -} - -bool TransferQueue::lockForUpdate(int index, const TileRenderInfo* renderInfo) -{ - // Before dequeuing the buffer from Surface Texture, make sure this item - // has been consumed. We can't simply rely on dequeueBuffer, due to the - // UI thread may want to remove the current operation, so we have to add - // our own locking mechanism. - // For blocking case, the item's status should not be emptyItem. - while (m_transferQueueItemLocks[index].tryLock()) { - // If the current operation is on an resource which is going to be - // removed from UI thread, then early return. - if (currentOpWaitingRemoval(renderInfo)) { - XLOG("Quit bitmap update: operation is removed from UI thread!" - " x y %d %d", - renderInfo->x, renderInfo->y); - return false; - } - } + if (!getHasGLContext()) + 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) + m_transferQueueItemCond.wait(m_transferQueueItemLocks); - // And if we have lost GL Context, then we can just early return here. - if (!getHasGLContext()) { - m_transferQueue[index].status = pendingDiscard; - m_transferQueueItemLocks[index].unlock(); - XLOG("Quit bitmap update: No GL Context! x y %d %d", - renderInfo->x, renderInfo->y); + if (!getHasGLContext()) return false; - } return true; } +// Both getHasGLContext and setHasGLContext should be called within the lock. bool TransferQueue::getHasGLContext() { - android::Mutex::Autolock lock(m_hasGLContextLock); - bool hasContext = m_hasGLContext; - return hasContext; + return m_hasGLContext; } void TransferQueue::setHasGLContext(bool hasContext) { - android::Mutex::Autolock lock(m_hasGLContextLock); m_hasGLContext = hasContext; } +// Only called when WebView is destroyed. void TransferQueue::discardQueue() { + android::Mutex::Autolock lock(m_transferQueueItemLocks); + + for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) + m_transferQueue[i].status = pendingDiscard; + + bool GLContextExisted = getHasGLContext(); // Unblock the Tex Gen thread first before Tile Page deletion. // Otherwise, there will be a deadlock while removing operations. setHasGLContext(false); - for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) { - m_transferQueue[i].status = pendingDiscard; - m_transferQueueItemLocks[i].unlock(); - } + // Only signal once when GL context lost. + if (GLContextExisted) + m_transferQueueItemCond.signal(); } // Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture. void TransferQueue::updateDirtyBaseTiles() { - bool unlockFlag[ST_BUFFER_NUMBER]; - memset(unlockFlag, 0, sizeof(unlockFlag)); - saveGLState(); - m_transferQueueLock.lock(); + android::Mutex::Autolock lock(m_transferQueueItemLocks); cleanupTransportQueue(); if (!getHasGLContext()) @@ -261,11 +232,11 @@ void TransferQueue::updateDirtyBaseTiles() m_sharedSurfaceTexture->updateTexImage(); - unlockFlag[index] = true; m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { XLOG("Warning: the texture is obsolete for this baseTile"); + index = (index + 1) % ST_BUFFER_NUMBER; continue; } @@ -290,24 +261,80 @@ void TransferQueue::updateDirtyBaseTiles() restoreGLState(); - int unlockIndex = nextItemIndex; - for (int k = 0; k < ST_BUFFER_NUMBER; k++) { - // Check the same order as the updateTexImage. - if (unlockFlag[unlockIndex]) - m_transferQueueItemLocks[unlockIndex].unlock(); - unlockIndex = (unlockIndex + 1) % ST_BUFFER_NUMBER; + m_emptyItemCount = ST_BUFFER_NUMBER; + m_transferQueueItemCond.signal(); +} + +void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, + int x, int y, const SkBitmap& bitmap) +{ + android::Mutex::Autolock lock(m_transferQueueItemLocks); + + bool ready = readyForUpdate(); + + if (!ready) { + XLOG("Quit bitmap update: not ready! for tile x y %d %d", + renderInfo->x, renderInfo->y); + return; } + // Dequeue the Surface Texture. + sp<ANativeWindow> ANW = m_ANW; + if (!ANW.get()) { + XLOG("ERROR: ANW is null"); + return; + } + ANativeWindowBuffer* anb; + + int status = ANW->dequeueBuffer(ANW.get(), &anb); + GLUtils::checkSurfaceTextureError("dequeueBuffer", status); + // a) Update surface texture + sp<android::GraphicBuffer> buf(new android::GraphicBuffer(anb, false)); + status |= ANW->lockBuffer(ANW.get(), buf->getNativeBuffer()); // Mutex Lock + GLUtils::checkSurfaceTextureError("lockBuffer", status); + + // Fill the buffer with the content of the bitmap + uint8_t* img = 0; + status |= buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); + GLUtils::checkSurfaceTextureError("lock", status); + + if (status == NO_ERROR) { + int row, col; + int bpp = 4; // Now we only deal with RGBA8888 format. + int width = TilesManager::instance()->tileWidth(); + int height = TilesManager::instance()->tileHeight(); + if (!x && !y && bitmap.width() == width && bitmap.height() == height) { + bitmap.lockPixels(); + uint8_t* bitmapOrigin = static_cast<uint8_t*>(bitmap.getPixels()); + // Copied line by line since we need to handle the offsets and stride. + for (row = 0 ; row < bitmap.height(); row ++) { + uint8_t* dst = &(img[(buf->getStride() * (row + x) + y) * bpp]); + uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); + memcpy(dst, src, bpp * bitmap.width()); + } + bitmap.unlockPixels(); + } else { + // TODO: implement the partial invalidate here! + XLOG("ERROR: don't expect to get here yet before we support partial inval"); + } + } + buf->unlock(); + + status = ANW->queueBuffer(ANW.get(), buf->getNativeBuffer()); + GLUtils::checkSurfaceTextureError("queueBuffer", status); - m_transferQueueLock.unlock(); + // b) After update the Surface Texture, now udpate the transfer queue info. + addItemInTransferQueue(renderInfo); + XLOG("Bitmap updated x, y %d %d, baseTile %p", + renderInfo->x, renderInfo->y, renderInfo->baseTile); } // Note that there should be lock/unlock around this function call. // Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap. -void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, - int index) +void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo) { - m_transferQueueIndex = index; + m_transferQueueIndex = (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER; + int index = m_transferQueueIndex; if (m_transferQueue[index].savedBaseTilePtr || m_transferQueue[index].status != emptyItem) { XLOG("ERROR update a tile which is dirty already @ index %d", index); @@ -325,34 +352,25 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, textureInfo->m_painter = renderInfo->tilePainter; textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount; + + m_emptyItemCount--; } -// Note: this need to be called within th m_transferQueueLock. +// Note: this need to be called within th lock. +// Only called by updateDirtyBaseTiles() for now void TransferQueue::cleanupTransportQueue() { - // We should call updateTexImage to the items first, - // then unlock. And we should start from the next item. - const int nextItemIndex = getNextTransferQueueIndex(); - bool needUnlock[ST_BUFFER_NUMBER]; - int index = nextItemIndex; + int index = getNextTransferQueueIndex(); for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) { - needUnlock[index] = false; if (m_transferQueue[index].status == pendingDiscard) { m_sharedSurfaceTexture->updateTexImage(); m_transferQueue[index].savedBaseTilePtr = 0; - m_transferQueue[index].status == emptyItem; - needUnlock[index] = true; + m_transferQueue[index].status = emptyItem; } index = (index + 1) % ST_BUFFER_NUMBER; } - index = nextItemIndex; - for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) { - if (needUnlock[index]) - m_transferQueueItemLocks[index].unlock(); - index = (index + 1) % ST_BUFFER_NUMBER; - } } void TransferQueue::saveGLState() diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h index e0046c3..8d9df68 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -49,52 +49,46 @@ public: void updateDirtyBaseTiles(); - // This queue can be accessed from UI and TexGen thread, therefore, we need - // a lock to protect its access - TileTransferData* m_transferQueue; - android::Mutex m_transferQueueLock; - void initSharedSurfaceTextures(int width, int height); - sp<ANativeWindow> m_ANW; - bool getHasGLContext(); - void setHasGLContext(bool hasContext); + void updateQueueWithBitmap(const TileRenderInfo* renderInfo, int x, int y, + const SkBitmap& bitmap); - int getNextTransferQueueIndex(); + void discardQueue(); - void addItemInTransferQueue(const TileRenderInfo* info, int index); + void addItemInTransferQueue(const TileRenderInfo* info); // Check if the item @ index is ready for update. // The lock will be done when returning true. - bool lockForUpdate(int index, const TileRenderInfo* renderInfo); + bool readyForUpdate(); - void discardQueue(); + // This queue can be accessed from UI and TexGen thread, therefore, we need + // a lock to protect its access + TileTransferData* m_transferQueue; - // Store info for currentOpWaitingRemoval() to tell which operation - // will be removed. - TilePainter* m_currentRemovingPaint; + // 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 + // dequeue operation, which will not succeed. B/c at this moment, we + // already lost the GL Context. + // Now we maintain a counter, which is m_emptyItemCount. When this reach + // 0, then we need the Tex Gen thread to wait. UI thread can signal this + // wait after calling updateTexImage at the draw call , or after WebView + // is destroyed. + android::Mutex m_transferQueueItemLocks; - // Return the buffer number. - int size(); + sp<ANativeWindow> m_ANW; private: - // Note that the m_transferQueueIndex only changed in the TexGen thread - // where we are going to move on to update the next item in the queue. - int m_transferQueueIndex; - - GLuint m_fboID; // The FBO used for copy the SurfTex to each tile - - GLuint m_sharedSurfaceTextureId; + bool getHasGLContext(); + void setHasGLContext(bool hasContext); - // GLContext can be lost when WebView destroyed. - bool m_hasGLContext; - android::Mutex m_hasGLContextLock; + int getNextTransferQueueIndex(); // Save and restore the GL State while switching from/to FBO. void saveGLState(); void setGLStateForCopy(int width, int height); void restoreGLState(); - GLState m_GLStateBeforeBlit; // Check the current transfer queue item is obsolete or not. bool checkObsolete(int index); @@ -103,21 +97,25 @@ private: // pendingDiscard items. void cleanupTransportQueue(); - // This function can tell Tex Gen thread whether or not the current - // operation need to be removed now. - bool currentOpWaitingRemoval(const TileRenderInfo* renderInfo); + void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, + GLuint srcTexId, GLenum srcTexTarget); - void blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, GLuint srcTexId, GLenum srcTexTarget); + // Note that the m_transferQueueIndex only changed in the TexGen thread + // where we are going to move on to update the next item in the queue. + int m_transferQueueIndex; - // Each element in the queue has its own lock, basically lock before update - // and unlock at drawGL time. - // This is similar to the internal lock from SurfaceTexture, but we can't - // naively rely on them since when tearing down, UI thread need to clean up - // the pending jobs in that Tex Gen thread, if the Tex Gen is waiting for - // Surface Texture, then we are stuck. - android::Mutex* m_transferQueueItemLocks; + GLuint m_fboID; // The FBO used for copy the SurfTex to each tile + GLuint m_sharedSurfaceTextureId; + + // GLContext can be lost when WebView destroyed. + bool m_hasGLContext; + + GLState m_GLStateBeforeBlit; sp<android::SurfaceTexture> m_sharedSurfaceTexture; + + android::Condition m_transferQueueItemCond; + int m_emptyItemCount; }; } // namespace WebCore |