summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android/TransferQueue.cpp
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/android/TransferQueue.cpp
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/android/TransferQueue.cpp')
-rw-r--r--Source/WebCore/platform/graphics/android/TransferQueue.cpp174
1 files changed, 96 insertions, 78 deletions
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()