summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2011-08-03 15:31:41 -0700
committerTeng-Hui Zhu <ztenghui@google.com>2011-08-03 17:01:59 -0700
commit51c84083c0059a8e849bf0031704b0ec402059f0 (patch)
treeba4b61a3237a34d0ab642c10f530effeb147c830 /Source/WebCore/platform/graphics
parent03137dd16df459ef3bee925373347982cb98124d (diff)
downloadexternal_webkit-51c84083c0059a8e849bf0031704b0ec402059f0.zip
external_webkit-51c84083c0059a8e849bf0031704b0ec402059f0.tar.gz
external_webkit-51c84083c0059a8e849bf0031704b0ec402059f0.tar.bz2
Finalize the sync part.
Improve the sync part for the Shared Surface Texture. Clean up the interface as much as possible. bug:5044597 Change-Id: I123cc520fb447aeb6e72e90149d1658a657740f7
Diffstat (limited to 'Source/WebCore/platform/graphics')
-rw-r--r--Source/WebCore/platform/graphics/android/BaseTile.cpp11
-rw-r--r--Source/WebCore/platform/graphics/android/GLUtils.cpp63
-rw-r--r--Source/WebCore/platform/graphics/android/TilesManager.cpp2
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp174
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.h76
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 5a6a158..d1fe51a 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