diff options
author | Teng-Hui Zhu <ztenghui@google.com> | 2011-09-23 15:58:09 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-09-23 15:58:09 -0700 |
commit | 301c476ad4d477afb9fa74823d6afa3188080202 (patch) | |
tree | 90ed794cc5fcb98206c1a94b114e11f9bf84945a | |
parent | 7a93ab421d2efc4dbc1061e52cfb381ae59b7219 (diff) | |
parent | 0960fe0e966317c4728542e9cfaa259523665900 (diff) | |
download | external_webkit-301c476ad4d477afb9fa74823d6afa3188080202.zip external_webkit-301c476ad4d477afb9fa74823d6afa3188080202.tar.gz external_webkit-301c476ad4d477afb9fa74823d6afa3188080202.tar.bz2 |
Merge "Enable the CPU upload path for Browser."
5 files changed, 159 insertions, 106 deletions
diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h index d2560dd..9c2d8a7 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -34,8 +34,6 @@ class SkCanvas; -#define DEBUG_TRANSFER_USING_CPU_UPLOAD 0 - namespace WebCore { class BaseTile; @@ -63,45 +61,6 @@ public: bool m_inverted; }; -// While in the queue, the BaseTile can be re-used, the updated bitmap -// can be discarded. In order to track this obsolete base tiles, we save -// the Tile's Info to make the comparison. -// At the time of base tile's dtor or webview destroy, we want to discard -// all the data in the queue. However, we have to do the Surface Texture -// update in the same GL context as the UI thread. So we mark the status -// as pendingDiscard, and delay the Surface Texture operation to the next -// draw call. - -enum TransferItemStatus { - emptyItem = 0, // S.T. buffer ready for new content - pendingBlit = 1, // Ready for bliting into tile's GL Tex. - pendingDiscard = 2 // Waiting for the next draw call to discard -}; - -class TileTransferData { -public: - TileTransferData() - : status(emptyItem) - , savedBaseTilePtr(0) - , m_syncKHR(EGL_NO_SYNC_KHR) - { - } - TransferItemStatus status; - BaseTile* savedBaseTilePtr; - TextureTileInfo tileInfo; -#if DEBUG_TRANSFER_USING_CPU_UPLOAD - SkBitmap bitmap; -#endif - // Sync object for GPU fence, this is the only the info passed from UI - // thread to Tex Gen thread. The reason of having this is due to the - // missing sync mechanism on Surface Texture on some vendor. b/5122031. - // Bascially the idea is that when UI thread utilize one buffer from - // the surface texture, we'll need to kick off the GPU commands, and only - // when those particular commands finish, we could write into this buffer - // again in Tex Gen thread. - EGLSyncKHR m_syncKHR; -}; - // DoubleBufferedTexture using a SkBitmap as backing mechanism class BaseTileTexture : public DoubleBufferedTexture { public: diff --git a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp index 9268ac0..f4df33a 100644 --- a/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/GaneshRenderer.cpp @@ -153,7 +153,7 @@ void GaneshRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva #if !DEPRECATED_SURFACE_TEXTURE_MODE TransferQueue* tileQueue = TilesManager::instance()->transferQueue(); eglSwapBuffers(eglGetCurrentDisplay(), tileQueue->m_eglSurface); - tileQueue->addItemInTransferQueue(&renderInfo); + tileQueue->addItemInTransferQueue(&renderInfo, GpuUpload, 0); tileQueue->unlockQueue(); #endif } diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp index a8451a6..dcc34d2 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.cpp +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -61,6 +61,7 @@ TransferQueue::TransferQueue() , m_sharedSurfaceTextureId(0) , m_hasGLContext(true) , m_currentDisplay(EGL_NO_DISPLAY) + , m_currentUploadType(DEFAULT_UPLOAD_TYPE) { memset(&m_GLStateBeforeBlit, 0, sizeof(m_GLStateBeforeBlit)); @@ -236,13 +237,14 @@ void TransferQueue::setHasGLContext(bool hasContext) m_hasGLContext = hasContext; } -// Only called when WebView is destroyed. +// Only called when WebView is destroyed or switching the uploadType. void TransferQueue::discardQueue() { android::Mutex::Autolock lock(m_transferQueueItemLocks); for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) - m_transferQueue[i].status = pendingDiscard; + if (m_transferQueue[i].status == pendingBlit) + m_transferQueue[i].status = pendingDiscard; bool GLContextExisted = getHasGLContext(); // Unblock the Tex Gen thread first before Tile Page deletion. @@ -257,9 +259,8 @@ void TransferQueue::discardQueue() // Call on UI thread to copy from the shared Surface Texture to the BaseTile's texture. void TransferQueue::updateDirtyBaseTiles() { -#if !DEBUG_TRANSFER_USING_CPU_UPLOAD - saveGLState(); -#endif + if (m_currentUploadType == GpuUpload) + saveGLState(); android::Mutex::Autolock lock(m_transferQueueItemLocks); cleanupTransportQueue(); @@ -278,9 +279,8 @@ void TransferQueue::updateDirtyBaseTiles() BaseTileTexture* destTexture = 0; if (!obsoleteBaseTile) destTexture = m_transferQueue[index].savedBaseTilePtr->backTexture(); -#if !DEBUG_TRANSFER_USING_CPU_UPLOAD - m_sharedSurfaceTexture->updateTexImage(); -#endif + if (m_transferQueue[index].uploadType == GpuUpload) + m_sharedSurfaceTexture->updateTexImage(); m_transferQueue[index].savedBaseTilePtr = 0; m_transferQueue[index].status = emptyItem; if (obsoleteBaseTile) { @@ -292,16 +292,16 @@ void TransferQueue::updateDirtyBaseTiles() // guarantee that we have a texture to blit into destTexture->requireTexture(); -#if DEBUG_TRANSFER_USING_CPU_UPLOAD - // Here we just need to upload the bitmap content to the GL Texture - GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0, - m_transferQueue[index].bitmap); -#else - blitTileFromQueue(m_fboID, destTexture, - m_sharedSurfaceTextureId, - m_sharedSurfaceTexture->getCurrentTextureTarget(), - index); -#endif + if (m_transferQueue[index].uploadType == CpuUpload) { + // Here we just need to upload the bitmap content to the GL Texture + GLUtils::updateTextureWithBitmap(destTexture->m_ownTextureId, 0, 0, + *m_transferQueue[index].bitmap); + } else { + blitTileFromQueue(m_fboID, destTexture, + m_sharedSurfaceTextureId, + m_sharedSurfaceTexture->getCurrentTextureTarget(), + index); + } // After the base tile copied into the GL texture, we need to // update the texture's info such that at draw time, readyFor @@ -319,9 +319,8 @@ void TransferQueue::updateDirtyBaseTiles() index = (index + 1) % ST_BUFFER_NUMBER; } -#if !DEBUG_TRANSFER_USING_CPU_UPLOAD - restoreGLState(); -#endif + if (m_currentUploadType == GpuUpload) + restoreGLState(); m_emptyItemCount = ST_BUFFER_NUMBER; m_transferQueueItemCond.signal(); @@ -332,55 +331,55 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, { m_transferQueueItemLocks.lock(); 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); return; } -#if !DEBUG_TRANSFER_USING_CPU_UPLOAD - // a) Dequeue the Surface Texture and write into the buffer - if (!m_ANW.get()) { - XLOG("ERROR: ANW is null"); - return; - } - - ANativeWindow_Buffer buffer; - if (ANativeWindow_lock(m_ANW.get(), &buffer, 0)) - return; + if (currentUploadType == GpuUpload) { + // a) Dequeue the Surface Texture and write into the buffer + if (!m_ANW.get()) { + XLOG("ERROR: ANW is null"); + return; + } - uint8_t* img = (uint8_t*)buffer.bits; - 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()); - if (buffer.stride != bitmap.width()) - // Copied line by line since we need to handle the offsets and stride. - for (row = 0 ; row < bitmap.height(); row ++) { - uint8_t* dst = &(img[buffer.stride * row * bpp]); - uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); - memcpy(dst, src, bpp * bitmap.width()); - } - else - memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); + ANativeWindow_Buffer buffer; + if (ANativeWindow_lock(m_ANW.get(), &buffer, 0)) + return; + + uint8_t* img = (uint8_t*)buffer.bits; + 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()); + if (buffer.stride != bitmap.width()) + // Copied line by line since we need to handle the offsets and stride. + for (row = 0 ; row < bitmap.height(); row ++) { + uint8_t* dst = &(img[buffer.stride * row * bpp]); + uint8_t* src = &(bitmapOrigin[bitmap.width() * row * bpp]); + memcpy(dst, src, bpp * bitmap.width()); + } + else + memcpy(img, bitmapOrigin, bpp * bitmap.width() * bitmap.height()); + + bitmap.unlockPixels(); + } else { + // TODO: implement the partial invalidate here! + XLOG("ERROR: don't expect to get here yet before we support partial inval"); + } - bitmap.unlockPixels(); - } else { - // TODO: implement the partial invalidate here! - XLOG("ERROR: don't expect to get here yet before we support partial inval"); + ANativeWindow_unlockAndPost(m_ANW.get()); } - ANativeWindow_unlockAndPost(m_ANW.get()); -#endif m_transferQueueItemLocks.lock(); // b) After update the Surface Texture, now udpate the transfer queue info. - addItemInTransferQueue(renderInfo); -#if DEBUG_TRANSFER_USING_CPU_UPLOAD - bitmap.copyTo(&(m_transferQueue[m_transferQueueIndex].bitmap), bitmap.config()); -#endif + addItemInTransferQueue(renderInfo, currentUploadType, &bitmap); + m_transferQueueItemLocks.unlock(); XLOG("Bitmap updated x, y %d %d, baseTile %p", renderInfo->x, renderInfo->y, renderInfo->baseTile); @@ -388,7 +387,9 @@ void TransferQueue::updateQueueWithBitmap(const TileRenderInfo* renderInfo, // Note that there should be lock/unlock around this function call. // Currently only called by GLUtils::updateSharedSurfaceTextureWithBitmap. -void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo) +void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo, + TextureUploadType type, + const SkBitmap* bitmap) { m_transferQueueIndex = (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER; @@ -400,6 +401,17 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo) m_transferQueue[index].savedBaseTilePtr = renderInfo->baseTile; m_transferQueue[index].status = pendingBlit; + m_transferQueue[index].uploadType = type; + if (type == CpuUpload && bitmap) { + // Lazily create the bitmap + if (!m_transferQueue[index].bitmap) { + m_transferQueue[index].bitmap = new SkBitmap(); + int w = bitmap->width(); + int h = bitmap->height(); + m_transferQueue[index].bitmap->setConfig(bitmap->config(), w, h); + } + bitmap->copyTo(m_transferQueue[index].bitmap, bitmap->config()); + } // Now fill the tileInfo. TextureTileInfo* textureInfo = &m_transferQueue[index].tileInfo; @@ -414,6 +426,15 @@ void TransferQueue::addItemInTransferQueue(const TileRenderInfo* renderInfo) m_emptyItemCount--; } +void TransferQueue::setTextureUploadType(TextureUploadType type) +{ + discardQueue(); + + 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() @@ -422,9 +443,11 @@ void TransferQueue::cleanupTransportQueue() for (int i = 0 ; i < ST_BUFFER_NUMBER; i++) { if (m_transferQueue[index].status == pendingDiscard) { -#if !DEBUG_TRANSFER_USING_CPU_UPLOAD - m_sharedSurfaceTexture->updateTexImage(); -#endif + // No matter what the current upload type is, as long as there has + // been a Surf Tex enqueue operation, this updateTexImage need to + // be called to keep things in sync. + if (m_transferQueue[index].uploadType == GpuUpload) + m_sharedSurfaceTexture->updateTexImage(); m_transferQueue[index].savedBaseTilePtr = 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 f773e41..200df25 100644 --- a/Source/WebCore/platform/graphics/android/TransferQueue.h +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -42,11 +42,72 @@ struct GLState { GLfloat clearColor[4]; }; + +// While in the queue, the BaseTile can be re-used, the updated bitmap +// can be discarded. In order to track this obsolete base tiles, we save +// the Tile's Info to make the comparison. +// At the time of base tile's dtor or webview destroy, we want to discard +// all the data in the queue. However, we have to do the Surface Texture +// update in the same GL context as the UI thread. So we mark the status +// as pendingDiscard, and delay the Surface Texture operation to the next +// draw call. + +enum TransferItemStatus { + emptyItem = 0, // S.T. buffer ready for new content + pendingBlit = 1, // Ready for bliting into tile's GL Tex. + pendingDiscard = 2 // Waiting for the next draw call to discard +}; + +enum TextureUploadType { + CpuUpload = 0, + GpuUpload = 1 +}; + +#define DEFAULT_UPLOAD_TYPE GpuUpload + +class TileTransferData { +public: + TileTransferData() + : status(emptyItem) + , savedBaseTilePtr(0) + , uploadType(DEFAULT_UPLOAD_TYPE) + , bitmap(0) + , m_syncKHR(EGL_NO_SYNC_KHR) + { + } + + ~TileTransferData() + { + // Bitmap will be created lazily, need to delete them at dtor. + delete bitmap; + } + + TransferItemStatus status; + BaseTile* savedBaseTilePtr; + TextureTileInfo tileInfo; + TextureUploadType uploadType; + // This is only useful in Cpu upload code path, so it will be dynamically + // lazily allocated. + SkBitmap* bitmap; + + // Sync object for GPU fence, this is the only the info passed from UI + // thread to Tex Gen thread. The reason of having this is due to the + // missing sync mechanism on Surface Texture on some vendor. b/5122031. + // Bascially the idea is that when UI thread utilize one buffer from + // the surface texture, we'll need to kick off the GPU commands, and only + // when those particular commands finish, we could write into this buffer + // again in Tex Gen thread. + EGLSyncKHR m_syncKHR; +}; + class TransferQueue { public: TransferQueue(); ~TransferQueue(); + // This will be called by the browser through nativeSetProperty + void setTextureUploadType(TextureUploadType type); + void updateDirtyBaseTiles(); void initSharedSurfaceTextures(int width, int height); @@ -56,8 +117,9 @@ public: void discardQueue(); - void addItemInTransferQueue(const TileRenderInfo* info); - + void addItemInTransferQueue(const TileRenderInfo* info, + TextureUploadType type, + const SkBitmap* bitmap); // Check if the item @ index is ready for update. // The lock will be done when returning true. bool readyForUpdate(); @@ -129,6 +191,10 @@ private: android::Condition m_transferQueueItemCond; EGLDisplay m_currentDisplay; + + // This should be GpuUpload for production, but for debug purpose or working + // around driver/HW issue, we can set it to CpuUpload. + TextureUploadType m_currentUploadType; }; } // namespace WebCore diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 39a370c..9d5ac59 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -2630,6 +2630,11 @@ static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jv TilesManager::instance()->setInvertedScreenContrast(contrast); return true; } + if (key == "enable_cpu_upload_path") { + TilesManager::instance()->transferQueue()->setTextureUploadType( + value == "true" ? CpuUpload : GpuUpload); + return true; + } return false; } |