From c5cb0bd6d52a91fa13db7e02874e712761dfaf27 Mon Sep 17 00:00:00 2001 From: Steve Block Date: Thu, 9 Jun 2011 19:59:55 +0100 Subject: Fix a bug in the V8 JNI bindings when creating JNI method signatures This was introduced by the latest merge to WebKit r82507. WebKit now uses a new JavaTypeString, distinct from JavaTypeObject, for representing strings in the JNI bridge. We need to account for this when building the JNI method signature. See https://bugs.webkit.org/show_bug.cgi?id=62389 for details. Bug: 4585284 Change-Id: I6a54679b954c32bf03d715da3c958c61baa5fecc --- Source/WebCore/bridge/jni/JavaMethodJobject.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp index 2f2802c..5df16f9 100644 --- a/Source/WebCore/bridge/jni/JavaMethodJobject.cpp +++ b/Source/WebCore/bridge/jni/JavaMethodJobject.cpp @@ -130,7 +130,13 @@ const char* JavaMethodJobject::signature() const appendClassName(signatureBuilder, javaClassName.data()); else { signatureBuilder.append(signatureFromJavaType(type)); +#if PLATFORM(ANDROID) + // FIXME: Upstream to WebKit + // https://bugs.webkit.org/show_bug.cgi?id=62389 + if (type == JavaTypeObject || type == JavaTypeString) { +#else if (type == JavaTypeObject) { +#endif appendClassName(signatureBuilder, javaClassName.data()); signatureBuilder.append(';'); } @@ -143,7 +149,13 @@ const char* JavaMethodJobject::signature() const appendClassName(signatureBuilder, returnType); else { signatureBuilder.append(signatureFromJavaType(m_returnType)); +#if PLATFORM(ANDROID) + // FIXME: Upstream to WebKit + // https://bugs.webkit.org/show_bug.cgi?id=62389 + if (m_returnType == JavaTypeObject || m_returnType == JavaTypeString) { +#else if (m_returnType == JavaTypeObject) { +#endif appendClassName(signatureBuilder, returnType); signatureBuilder.append(';'); } -- cgit v1.1 From ba93a0db358764b99d9fa98857d19fb0e01eccd9 Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Wed, 22 Jun 2011 11:42:43 -0700 Subject: Browser ST: Lower the upper limit for texture allocation Change-Id: Ie88de19e89e298b69b106fbb42d2b9d26bb98014 --- Source/WebCore/platform/graphics/android/TilesManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 5a9a164..e4e8af7 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -57,8 +57,12 @@ // In our case, we use 300x300 textures. On the tablet, this equates to // at least 5 * 3 = 15 textures. We also enable offscreen textures to a maximum // of 101 textures used (i.e. ~70Mb max, accounting for the double buffer textures) -#define EXPANDED_TILE_BOUNDS_X 1 -#define EXPANDED_TILE_BOUNDS_Y 2 +// Now we switch to Surface Texture, which is triple buffering. In order to +// avoid OOM issue, we limit the bounds number to 0. +// TODO: We should either dynamically change the outer bound by detecting the +// HW limit or save further in the GPU memory consumption. +#define EXPANDED_TILE_BOUNDS_X 0 +#define EXPANDED_TILE_BOUNDS_Y 0 #define MAX_TEXTURE_ALLOCATION 3+(5+EXPANDED_TILE_BOUNDS_X*2)*(3+EXPANDED_TILE_BOUNDS_Y*2)*2 #define TILE_WIDTH 300 #define TILE_HEIGHT 300 -- cgit v1.1 From c4db15adc1b1c8d04397a9b2226ebd20fb5cc91b Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Mon, 27 Jun 2011 17:36:10 -0700 Subject: Delete the GL texture when deleting the Surface Texture Otherwise, there will be GPU memory leak. bug:4947376 Change-Id: Ib76a47c197d7c1a01471c4b38e210e0d5dd9fa02 --- Source/WebCore/platform/graphics/android/SharedTexture.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.cpp b/Source/WebCore/platform/graphics/android/SharedTexture.cpp index cbe44da..4f52107 100644 --- a/Source/WebCore/platform/graphics/android/SharedTexture.cpp +++ b/Source/WebCore/platform/graphics/android/SharedTexture.cpp @@ -78,6 +78,7 @@ SharedTexture::~SharedTexture() else if (m_sharedTextureMode == SurfaceTextureMode) { m_sourceTexture->m_surfaceTexture.clear(); m_sourceTexture->m_ANW.clear(); + GLUtils::deleteTexture(&m_sourceTexture->m_textureId); } delete m_sourceTexture; delete m_targetTexture; -- cgit v1.1 From b2b2600ead9272b959fd3317912152b55e81553e Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Wed, 29 Jun 2011 16:48:13 -0700 Subject: Don't create newer LayerTexture when hitting upper bound. bug:4976882 Change-Id: If1c913da8bdc3a310a3a665dc895711093fb8788 --- Source/WebCore/platform/graphics/android/TilesManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index b4df0a1..2259072 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -355,6 +355,10 @@ LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const Int if (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION) cleanupLayersTextures(layer, true); + // If the cleanup can't achieve the goal, then don't create a layerTexture. + if (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION) + return 0; + LayerTexture* texture = new LayerTexture(w, h); texture->setId(layer->uniqueId()); texture->setRect(rect); -- cgit v1.1 From d50f97e065319b23ff12c2fd43df4cd83d1ccccf Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Mon, 1 Aug 2011 11:32:58 -0700 Subject: Shared surface texture Instead of assigning each tile a Surface Texture, now just a normal GL texture. The content from skia bitmap will first drawn into a queue of Surface Textures, at draw time, blit them into each tile's GL texture. Added extra lock to protect the queue operation and Surface Texture operation. bug:5044597 Change-Id: I25f46228b93a3e99526daf52d8bd0d8d8fcc2879 --- Source/WebCore/Android.mk | 1 + .../platform/graphics/android/BaseRenderer.cpp | 2 +- .../WebCore/platform/graphics/android/BaseTile.cpp | 26 +- .../platform/graphics/android/BaseTileTexture.cpp | 50 ++- .../platform/graphics/android/BaseTileTexture.h | 66 +++- .../WebCore/platform/graphics/android/GLUtils.cpp | 154 +++++++- Source/WebCore/platform/graphics/android/GLUtils.h | 12 +- .../platform/graphics/android/GLWebViewState.cpp | 10 +- .../platform/graphics/android/LayerAndroid.cpp | 6 +- .../platform/graphics/android/RasterRenderer.cpp | 3 +- .../platform/graphics/android/ShaderProgram.cpp | 13 +- .../platform/graphics/android/SharedTexture.cpp | 6 + .../platform/graphics/android/TextureInfo.cpp | 3 + .../platform/graphics/android/TextureInfo.h | 9 +- .../platform/graphics/android/TiledTexture.cpp | 8 +- .../platform/graphics/android/TilesManager.cpp | 14 +- .../platform/graphics/android/TilesManager.h | 5 +- .../platform/graphics/android/TransferQueue.cpp | 403 +++++++++++++++++++++ .../platform/graphics/android/TransferQueue.h | 126 +++++++ 19 files changed, 848 insertions(+), 69 deletions(-) create mode 100644 Source/WebCore/platform/graphics/android/TransferQueue.cpp create mode 100644 Source/WebCore/platform/graphics/android/TransferQueue.h diff --git a/Source/WebCore/Android.mk b/Source/WebCore/Android.mk index c803c5f..d814c1a 100644 --- a/Source/WebCore/Android.mk +++ b/Source/WebCore/Android.mk @@ -676,6 +676,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ platform/graphics/android/TilesProfiler.cpp \ platform/graphics/android/TiledPage.cpp \ platform/graphics/android/TiledTexture.cpp \ + platform/graphics/android/TransferQueue.cpp \ platform/graphics/android/VideoLayerAndroid.cpp \ platform/graphics/android/VideoLayerManager.cpp \ platform/graphics/android/android_graphics.cpp \ diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp index ea6c8ec..cafab4a 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp @@ -154,7 +154,7 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) if (renderInfo.measurePerf) drawTileInfo(&canvas, renderInfo, pictureCount); } - + renderInfo.textureInfo->m_pictureCount = pictureCount; renderingComplete(renderInfo, &canvas); return pictureCount; } diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 6ab2cd2..8bc560e 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -92,6 +92,17 @@ 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); @@ -239,16 +250,14 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale) } if (m_texture->readyFor(this)) { - XLOG("draw tile %x : %d, %d, %.2f with texture %x", this, x(), y(), scale(), m_texture); + XLOG("draw tile %x : %d, %d, %.2f with texture %x", this, x(), y(), m_scale, m_texture); if (isLayerTile()) TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(), - rect, textureInfo->m_textureId, - transparency, true, - textureInfo->getTextureTarget()); + rect, m_texture->m_ownTextureId, + transparency, true); else - TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, - transparency, - textureInfo->getTextureTarget()); + TilesManager::instance()->shader()->drawQuad(rect, m_texture->m_ownTextureId, + transparency); } m_texture->consumerRelease(); } @@ -400,7 +409,10 @@ void BaseTile::paintBitmap() XLOG("%x update texture %x for tile %d, %d scale %.2f (m_scale: %.2f)", this, textureInfo, x, y, scale, m_scale); m_atomicSync.lock(); + +#if DEPRECATED_SURFACE_TEXTURE_MODE texture->setTile(textureInfo, x, y, scale, painter, pictureCount); +#endif texture->producerReleaseAndSwap(); if (texture == m_texture) { diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index 8419e80..c964e04 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -32,9 +32,20 @@ #include "GLUtils.h" #include "TilesManager.h" -#define LOG_NDEBUG 1 -#define LOG_TAG "BaseTileTexture.cpp" -#include +#ifdef DEBUG + +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG namespace WebCore { @@ -48,6 +59,10 @@ BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h) , m_busy(false) { m_size.set(w, h); + m_ownTextureId = GLUtils::createBaseTileGLTexture(w, h); + + // Make sure they are created on the UI thread. + TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTileTexture"); @@ -130,7 +145,9 @@ void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& b return; } - GLUtils::paintTextureWithBitmap(textureInfo, m_size, bitmap, 0, 0); + // After the tiled layer checked in, this is not called anyway. + // TODO: cleanup the old code path for layer painting + // GLUtils::paintTextureWithBitmap(info, m_size, bitmap, 0, 0); producerReleaseAndSwap(); } @@ -225,23 +242,36 @@ void BaseTileTexture::setTile(TextureInfo* info, int x, int y, float BaseTileTexture::scale() { - TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); - if (!textureInfo) - return 1.0; + TextureTileInfo* textureInfo = &m_ownTextureTileInfo; return textureInfo->m_scale; } +// This function + TilesManager::addItemInTransferQueue() is replacing the +// setTile(). +void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info) +{ + m_ownTextureTileInfo.m_x = info->m_x; + m_ownTextureTileInfo.m_y = info->m_y; + m_ownTextureTileInfo.m_scale = info->m_scale; + m_ownTextureTileInfo.m_painter = info->m_painter; + m_ownTextureTileInfo.m_picture = info->m_picture; +} + bool BaseTileTexture::readyFor(BaseTile* baseTile) { - TextureTileInfo* info = m_texturesInfo.get(getReadableTexture()); + const TextureTileInfo* info = &m_ownTextureTileInfo; if (info && (info->m_x == baseTile->x()) && (info->m_y == baseTile->y()) && (info->m_scale == baseTile->scale()) && (info->m_painter == baseTile->painter()) && - (info->m_picture == baseTile->lastPaintedPicture())) { + (info->m_picture == baseTile->lastPaintedPicture())) return true; - } + + XLOG("readyFor return false for tile x, y (%d %d) texId %d ," + " BaseTileTexture %p, BaseTile is %p", + baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile); + return false; } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h index 0cdd137..b21659f 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -40,23 +40,50 @@ class BaseTile; class TextureTileInfo { public: - TextureTileInfo() - : m_x(-1) - , m_y(-1) - , m_layerId(-1) - , m_scale(0) - , m_texture(0) - , m_painter(0) - , m_picture(0) - { - } - int m_x; - int m_y; - int m_layerId; - float m_scale; - TextureInfo* m_texture; - TilePainter* m_painter; - unsigned int m_picture; + TextureTileInfo() + : m_x(-1) + , m_y(-1) + , m_layerId(-1) + , m_scale(0) + , m_texture(0) + , m_painter(0) + , m_picture(0) + { + } + int m_x; + int m_y; + int m_layerId; + float m_scale; + TextureInfo* m_texture; + TilePainter* m_painter; + unsigned int m_picture; +}; + +// 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) + { + } + TransferItemStatus status; + BaseTile* savedBaseTilePtr; + TextureTileInfo tileInfo; }; // DoubleBufferedTexture using a SkBitmap as backing mechanism @@ -108,11 +135,16 @@ public: bool readyFor(BaseTile* baseTile); float scale(); + GLuint m_ownTextureId; + + void setOwnTextureTileInfoFromQueue(const TextureTileInfo* info); + protected: HashMap m_texturesInfo; private: void destroyTextures(SharedTexture** textures); + TextureTileInfo m_ownTextureTileInfo; SkSize m_size; int m_usedLevel; diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index 1f04ff5..5a6a158 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -29,15 +29,29 @@ #if USE(ACCELERATED_COMPOSITING) #include "ShaderProgram.h" +#include "TilesManager.h" #include #include #include #include + +#ifdef DEBUG + +#include +#include + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "GLUtils", __VA_ARGS__) +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + struct ANativeWindowBuffer; namespace WebCore { @@ -112,8 +126,9 @@ static void crashIfOOM(GLint errorCode) { void GLUtils::checkEglError(const char* op, EGLBoolean returnVal) { - if (returnVal != EGL_TRUE) + if (returnVal != EGL_TRUE) { XLOG("EGL ERROR - %s() returned %d\n", op, returnVal); + } for (EGLint error = eglGetError(); error != EGL_SUCCESS; error = eglGetError()) { XLOG("after %s() eglError (0x%x)\n", op, error); @@ -145,8 +160,9 @@ bool GLUtils::checkGlErrorOn(void* p, const char* op) void GLUtils::checkSurfaceTextureError(const char* functionName, int status) { - if (status != NO_ERROR) + if (status != NO_ERROR) { XLOG("ERROR at calling %s status is (%d)", functionName, status); + } } ///////////////////////////////////////////////////////////////////////////////////////// // GL & EGL extension checks @@ -336,17 +352,46 @@ GLuint GLUtils::createSampleTexture() return texture; } -void GLUtils::paintTextureWithBitmap(TextureInfo* textureInfo, - const SkSize& requiredSize, - const SkBitmap& bitmap, - int x, int y) +GLuint GLUtils::createBaseTileGLTexture(int width, int height) +{ + GLuint texture; + glGenTextures(1, &texture); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + GLubyte* pixels = 0; +#ifdef DEBUG + int length = width * height * 4; + pixels = new GLubyte[length]; + for (int i = 0; i < length; i++) + pixels[i] = i % 256; +#endif + glBindTexture(GL_TEXTURE_2D, texture); + GLUtils::checkGlError("glBindTexture"); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + GLUtils::checkGlError("glTexImage2D"); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + return texture; +} + +void GLUtils::paintTextureWithBitmap(const TileRenderInfo* renderInfo, + const SkBitmap& bitmap) { + if (!renderInfo) + return; + const int x = renderInfo->invalRect->fLeft; + const int y = renderInfo->invalRect->fTop; + const SkSize& requiredSize = renderInfo->tileSize; + TextureInfo* textureInfo = renderInfo->textureInfo; SharedTextureMode mode = textureInfo->getSharedTextureMode(); if (requiredSize.equals(textureInfo->m_width, textureInfo->m_height)) { if (mode == EglImageMode) GLUtils::updateTextureWithBitmap(textureInfo->m_textureId, x, y, bitmap); else if (mode == SurfaceTextureMode) - GLUtils::updateSurfaceTextureWithBitmap(textureInfo, x, y, bitmap); +#if DEPRECATED_SURFACE_TEXTURE_MODE + GLUtils::updateSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); +#else + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, x, y, bitmap); +#endif } else { if (!requiredSize.equals(bitmap.width(), bitmap.height())) { @@ -358,22 +403,30 @@ void GLUtils::paintTextureWithBitmap(TextureInfo* textureInfo, if (mode == EglImageMode) GLUtils::createTextureWithBitmap(textureInfo->m_textureId, bitmap); else if (mode == SurfaceTextureMode) - GLUtils::createSurfaceTextureWithBitmap(textureInfo, bitmap); - +#if DEPRECATED_SURFACE_TEXTURE_MODE + GLUtils::createSurfaceTextureWithBitmap(renderInfo, bitmap); +#else + GLUtils::updateSharedSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap); +#endif textureInfo->m_width = bitmap.width(); textureInfo->m_height = bitmap.height(); + textureInfo->m_internalFormat = GL_RGBA; } } -void GLUtils::createSurfaceTextureWithBitmap(TextureInfo* texture, const SkBitmap& bitmap, GLint filter) +#if DEPRECATED_SURFACE_TEXTURE_MODE +void GLUtils::createSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap, GLint filter) { - sp surfaceTexture = texture->m_surfaceTexture; - sp ANW = texture->m_ANW; + + TextureInfo* texture = renderInfo->textureInfo; texture->m_width = bitmap.width(); texture->m_height = bitmap.height(); texture->m_internalFormat = GL_RGBA; + sp surfaceTexture = texture->m_surfaceTexture; + sp ANW = texture->m_ANW; + int result; result = native_window_set_buffers_geometry(ANW.get(), texture->m_width, texture->m_height, HAL_PIXEL_FORMAT_RGBA_8888); @@ -382,11 +435,12 @@ void GLUtils::createSurfaceTextureWithBitmap(TextureInfo* texture, const SkBitma GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); checkSurfaceTextureError("native_window_set_usage", result); - updateSurfaceTextureWithBitmap(texture, 0, 0, bitmap, filter); + updateSurfaceTextureWithBitmap(renderInfo, 0, 0, bitmap, filter); } -void GLUtils::updateSurfaceTextureWithBitmap(TextureInfo* texture, int x, int y, const SkBitmap& bitmap, GLint filter) +void GLUtils::updateSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap, GLint filter) { + TextureInfo* texture = renderInfo->textureInfo; sp surfaceTexture = texture->m_surfaceTexture; sp ANW = texture->m_ANW; @@ -426,6 +480,78 @@ void GLUtils::updateSurfaceTextureWithBitmap(TextureInfo* texture, int x, int y, status = ANW->queueBuffer(ANW.get(), buf->getNativeBuffer()); checkSurfaceTextureError("queueBuffer", status); } +#endif + +void GLUtils::updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* renderInfo, int x, int y, const SkBitmap& bitmap) +{ + if (!renderInfo + || !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 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 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(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(); +} void GLUtils::createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter) { diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index a015136..57557b2 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -64,15 +64,19 @@ public: static void deleteTexture(GLuint* texture); static GLuint createSampleColorTexture(int r, int g, int b); static GLuint createSampleTexture(); + static GLuint createBaseTileGLTexture(int width, int height); + static void createTextureWithBitmap(GLuint texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); static void updateTextureWithBitmap(GLuint texture, int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); static void createEGLImageFromTexture(GLuint texture, EGLImageKHR* image); static void createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint filter = GL_LINEAR); - static void paintTextureWithBitmap(TextureInfo* textureInfo, const SkSize& requiredSize, const SkBitmap& bitmap, int x, int y); - - static void createSurfaceTextureWithBitmap(TextureInfo* texture, const SkBitmap& bitmap, GLint filter = GL_LINEAR); - static void updateSurfaceTextureWithBitmap(TextureInfo* texture, int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void paintTextureWithBitmap(const TileRenderInfo* renderInfo, const SkBitmap& bitmap); +#if DEPRECATED_SURFACE_TEXTURE_MODE + static void createSurfaceTextureWithBitmap(const TileRenderInfo* , const SkBitmap& bitmap, GLint filter = GL_LINEAR); + static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); +#endif + static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap); }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 07dda03..df8ecbe 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -104,6 +104,9 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex) GLWebViewState::~GLWebViewState() { + // Take care of the transfer queue such that Tex Gen thread will not stuck + TilesManager::instance()->unregisterGLWebViewState(this); + // We have to destroy the two tiled pages first as their destructor // may depend on the existence of this GLWebViewState and some of its // instance variables in order to complete. @@ -121,7 +124,7 @@ GLWebViewState::~GLWebViewState() #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("GLWebViewState"); #endif - TilesManager::instance()->unregisterGLWebViewState(this); + } void GLWebViewState::setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, @@ -544,6 +547,11 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, if (baseForComposited && baseForComposited->countChildren() >= 1) compositedRoot = static_cast(baseForComposited->getChild(0)); + // Here before we draw, update the BaseTile which has updated content. + // Inside this function, just do GPU blits from the transfer queue into + // the BaseTiles' texture. + TilesManager::instance()->transferQueue()->updateDirtyBaseTiles(); + if (compositedRoot != m_previouslyUsedRoot) { TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot); TilesManager::instance()->cleanupTilesTextures(); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 05cb85e..00db27c 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -683,7 +683,7 @@ void LayerAndroid::showLayer(int indent) { char spaces[256]; memset(spaces, 0, 256); - for (unsigned int i = 0; i < indent; i++) + for (int i = 0; i < indent; i++) spaces[i] = ' '; if (!indent) @@ -745,10 +745,10 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) } // When the layer is dirty, the UI thread should be notified to redraw. - askPaint = drawChildrenGL(glWebViewState, matrix); + askPaint |= drawChildrenGL(glWebViewState, matrix); m_atomicSync.lock(); askPaint |= m_dirty; - if ((m_dirty && needsTexture()) || m_hasRunningAnimations || m_drawTransform.hasPerspective()) + if (askPaint || m_hasRunningAnimations || m_drawTransform.hasPerspective()) addDirtyArea(glWebViewState); m_atomicSync.unlock(); diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index 4a18861..f66c7c1 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -121,8 +121,7 @@ void RasterRenderer::renderingComplete(const TileRenderInfo& renderInfo, SkCanva const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - GLUtils::paintTextureWithBitmap(renderInfo.textureInfo, renderInfo.tileSize, - bitmap, renderInfo.invalRect->fLeft, renderInfo.invalRect->fTop); + GLUtils::paintTextureWithBitmap(&renderInfo, bitmap); if (renderInfo.measurePerf) m_perfMon.stop(TAG_UPDATE_TEXTURE); diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp index c4abeab..c9d2d56 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -346,7 +346,18 @@ void ShaderProgram::drawQuadInternal(SkRect& geometry, GLint contrast) { glUseProgram(program); - setProjectionMatrix(geometry, projectionMatrixHandle); + + if (!geometry.isEmpty()) + setProjectionMatrix(geometry, projectionMatrixHandle); + else { + TransformationMatrix matrix; + // Map x,y from (0,1) to (-1, 1) + matrix.scale3d(2, 2, 1); + matrix.translate3d(-0.5, -0.5, 0); + GLfloat projectionMatrix[16]; + GLUtils::toGLMatrix(projectionMatrix, matrix); + glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix); + } glActiveTexture(GL_TEXTURE0); glUniform1i(texSampler, 0); diff --git a/Source/WebCore/platform/graphics/android/SharedTexture.cpp b/Source/WebCore/platform/graphics/android/SharedTexture.cpp index a7d43b5..74cd2c6 100644 --- a/Source/WebCore/platform/graphics/android/SharedTexture.cpp +++ b/Source/WebCore/platform/graphics/android/SharedTexture.cpp @@ -57,12 +57,14 @@ SharedTexture::SharedTexture(SharedTextureMode mode) m_supportsEGLImage = false; m_supportsEGLFenceSyncKHR = false; } else if (m_sharedTextureMode == SurfaceTextureMode) { +#if DEPRECATED_SURFACE_TEXTURE_MODE glGenTextures(1, &m_sourceTexture->m_textureId); m_sourceTexture->m_surfaceTexture = new android::SurfaceTexture(m_sourceTexture->m_textureId, false); m_sourceTexture->m_ANW = new android::SurfaceTextureClient(m_sourceTexture->m_surfaceTexture); +#endif } } @@ -74,9 +76,11 @@ SharedTexture::~SharedTexture() if (m_sharedTextureMode == EglImageMode) deleteTargetTexture(); else if (m_sharedTextureMode == SurfaceTextureMode) { +#if DEPRECATED_SURFACE_TEXTURE_MODE m_sourceTexture->m_surfaceTexture.clear(); m_sourceTexture->m_ANW.clear(); GLUtils::deleteTexture(&m_sourceTexture->m_textureId); +#endif } delete m_sourceTexture; delete m_targetTexture; @@ -196,7 +200,9 @@ TextureInfo* SharedTexture::lockTarget() { // Note that the source and targe are the same when using Surface Texture. if (m_sharedTextureMode == SurfaceTextureMode) { +#if DEPRECATED_SURFACE_TEXTURE_MODE m_sourceTexture->m_surfaceTexture->updateTexImage(); +#endif return m_sourceTexture; } diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.cpp b/Source/WebCore/platform/graphics/android/TextureInfo.cpp index 5db1711..8b3da8e 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.cpp +++ b/Source/WebCore/platform/graphics/android/TextureInfo.cpp @@ -43,6 +43,7 @@ TextureInfo::TextureInfo(SharedTextureMode mode) m_internalFormat = 0; m_sharedTextureMode = mode; m_eglSurface = EGL_NO_SURFACE; + m_pictureCount = 0; } bool TextureInfo::equalsAttributes(const TextureInfo* otherTexture) @@ -66,6 +67,7 @@ bool TextureInfo::operator==(const TextureInfo& otherTexture) GLenum TextureInfo::getTextureTarget() { +#if DEPRECATED_SURFACE_TEXTURE_MODE if (m_surfaceTexture.get()) { GLenum target = m_surfaceTexture->getCurrentTextureTarget(); // TODO: remove this translation when TEXTURE_2D+RGBA surface texture @@ -74,6 +76,7 @@ GLenum TextureInfo::getTextureTarget() return 0; return target; } +#endif return GL_TEXTURE_2D; } diff --git a/Source/WebCore/platform/graphics/android/TextureInfo.h b/Source/WebCore/platform/graphics/android/TextureInfo.h index c1cb1cd..fda85da 100644 --- a/Source/WebCore/platform/graphics/android/TextureInfo.h +++ b/Source/WebCore/platform/graphics/android/TextureInfo.h @@ -31,9 +31,11 @@ #include #include #include - +#include "BaseTile.h" using android::sp; +#define DEPRECATED_SURFACE_TEXTURE_MODE 0 + namespace android { class SurfaceTexture; } @@ -68,12 +70,15 @@ public: GLenum m_internalFormat; // Surface Texture specific data +#if DEPRECATED_SURFACE_TEXTURE_MODE sp m_surfaceTexture; +#endif + // TODO: Delete this after the Ganesh code path get fixed. sp m_ANW; - // The EGLSurface wraps the m_ANW to enable direct OpenGL rendering (e.g. Ganesh) EGLSurface m_eglSurface; + int m_pictureCount; private: SharedTextureMode m_sharedTextureMode; }; diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp index 3dc0956..66846fe 100644 --- a/Source/WebCore/platform/graphics/android/TiledTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -82,15 +82,15 @@ void TiledTexture::prepare(GLWebViewState* state, bool repaint) m_area.setWidth(area.width() / tileWidth); m_area.setHeight(area.height() / tileHeight); - XLOG("for TiledTexture %x, we have a visible area of %d x %d, corresponding to %d x %d tiles", - this, visibleArea.width(), visibleArea.height(), - m_area.width(), m_area.height()); - if (m_area.width() * tileWidth < area.width()) m_area.setWidth(m_area.width() + 1); if (m_area.height() * tileHeight < area.height()) m_area.setHeight(m_area.height() + 1); + XLOG("for TiledTexture %x, we have a visible area of %d x %d, corresponding to %d x %d tiles", + this, visibleArea.width(), visibleArea.height(), + m_area.width(), m_area.height()); + bool goingDown = m_prevTileY < m_area.y(); m_prevTileY = m_area.y(); diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 6a294b0..402f4ec 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -33,7 +33,10 @@ #include "SkCanvas.h" #include "SkDevice.h" #include "SkPaint.h" +#include #include +#include +#include #include @@ -101,8 +104,8 @@ TilesManager::TilesManager() , m_expandedTileBounds(false) , m_generatorReady(false) , m_showVisualIndicator(false) - , m_drawRegistrationCount(0) , m_invertedScreen(false) + , m_drawRegistrationCount(0) { XLOG("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); @@ -190,7 +193,7 @@ void TilesManager::addPaintedSurface(PaintedSurface* surface) void TilesManager::cleanupTilesTextures() { // release existing surfaces without layers - Vector collect; + WTF::Vector collect; for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) { PaintedSurface* surface = m_paintedSurfaces[i]; if (!surface->layer()) @@ -200,7 +203,10 @@ void TilesManager::cleanupTilesTextures() for (unsigned int i = 0; i < collect.size(); i++) { 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]; } @@ -365,6 +371,10 @@ void TilesManager::registerGLWebViewState(GLWebViewState* state) void TilesManager::unregisterGLWebViewState(GLWebViewState* state) { + // Discard the whole queue b/c we lost GL context already. + // Note the real updateTexImage will still wait for the next draw. + transferQueue()->discardQueue(); + m_glWebViewStateMap.remove(state); XLOG("state %p now removed, total of %d states", state, m_glWebViewStateMap.size()); } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 25f6ba2..e884fc0 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -36,6 +36,7 @@ #include "TiledPage.h" #include "TilesProfiler.h" #include "TilesTracker.h" +#include "TransferQueue.h" #include "VideoLayerManager.h" #include #include @@ -84,6 +85,7 @@ public: void addPaintedSurface(PaintedSurface* surface); ShaderProgram* shader() { return &m_shader; } + TransferQueue* transferQueue() { return &m_queue; } VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } BaseTileTexture* getAvailableTexture(BaseTile* owner); @@ -155,7 +157,6 @@ public: } private: - TilesManager(); void waitForGenerator() @@ -188,6 +189,8 @@ private: static TilesManager* gInstance; ShaderProgram m_shader; + TransferQueue m_queue; + VideoLayerManager m_videoLayerManager; HashMap m_glWebViewStateMap; diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/TransferQueue.cpp new file mode 100644 index 0000000..878affb --- /dev/null +++ b/Source/WebCore/platform/graphics/android/TransferQueue.cpp @@ -0,0 +1,403 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "TransferQueue.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "PaintedSurface.h" +#include +#include +#include + +#ifdef DEBUG +#include +#include + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TransferQueue", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +#define ST_BUFFER_NUMBER 4 + +namespace WebCore { + +TransferQueue::TransferQueue() + : m_currentRemovingPaint(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_transferQueue = new TileTransferData[ST_BUFFER_NUMBER]; + for (int i = 0; i < ST_BUFFER_NUMBER; i++) { + m_transferQueue[i].savedBaseTilePtr = 0; + m_transferQueue[i].status = emptyItem; + } +} + +TransferQueue::~TransferQueue() +{ + glDeleteFramebuffers(1, &m_fboID); + m_fboID = 0; + 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) { + glGenTextures(1, &m_sharedSurfaceTextureId); + m_sharedSurfaceTexture = + new android::SurfaceTexture(m_sharedSurfaceTextureId); + m_ANW = new android::SurfaceTextureClient(m_sharedSurfaceTexture); + m_sharedSurfaceTexture->setSynchronousMode(true); + m_sharedSurfaceTexture->setBufferCount(ST_BUFFER_NUMBER+1); + + int result = native_window_set_buffers_geometry(m_ANW.get(), + width, height, HAL_PIXEL_FORMAT_RGBA_8888); + GLUtils::checkSurfaceTextureError("native_window_set_buffers_geometry", result); + result = native_window_set_usage(m_ANW.get(), + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + GLUtils::checkSurfaceTextureError("native_window_set_usage", result); + } + + if (!m_fboID) + glGenFramebuffers(1, &m_fboID); +} + +// When bliting, if the item from the transfer queue is mismatching b/t the +// BaseTile and the content, then the item is considered as obsolete, and +// the content is discarded. +bool TransferQueue::checkObsolete(int index) +{ + BaseTile* baseTilePtr = m_transferQueue[index].savedBaseTilePtr; + if (!baseTilePtr) { + XLOG("Invalid savedBaseTilePtr , such that the tile is obsolete"); + return true; + } + + BaseTileTexture* baseTileTexture = baseTilePtr->texture(); + if (!baseTileTexture) { + XLOG("Invalid baseTileTexture , such that the tile is obsolete"); + return true; + } + + const TextureTileInfo* tileInfo = &m_transferQueue[index].tileInfo; + + if (tileInfo->m_x != baseTilePtr->x() + || tileInfo->m_y != baseTilePtr->y() + || tileInfo->m_scale != baseTilePtr->scale() + || tileInfo->m_painter != baseTilePtr->painter()) { + XLOG("Mismatching x, y, scale or painter , such that the tile is obsolete"); + return true; + } + + return false; +} + +void TransferQueue::blitTileFromQueue(GLuint fboID, BaseTileTexture* destTex, GLuint srcTexId, GLenum srcTexTarget) +{ + // Then set up the FBO and copy the SurfTex content in. + glBindFramebuffer(GL_FRAMEBUFFER, fboID); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + destTex->m_ownTextureId, + 0); + setGLStateForCopy(destTex->getSize().width(), + destTex->getSize().height()); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + XLOG("Error: glCheckFramebufferStatus failed"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + return; + } + + // Use empty rect to set up the special matrix to draw. + SkRect rect = SkRect::MakeEmpty(); + TilesManager::instance()->shader()->drawQuad(rect, srcTexId, 1.0, + srcTexTarget); + + // Need to WAR a driver bug to add a sync point here + GLubyte readBackPixels[4]; + glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, readBackPixels); + + // Clean up FBO setup. + glBindFramebuffer(GL_FRAMEBUFFER, 0); // rebind the standard FBO + GLUtils::checkGlError("copy the surface texture into the normal one"); +} + +bool TransferQueue::currentOpWaitingRemoval(const TileRenderInfo* renderInfo) +{ + 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; + } + } + + // 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); + return false; + } + + return true; +} + +bool TransferQueue::getHasGLContext() +{ + android::Mutex::Autolock lock(m_hasGLContextLock); + bool hasContext = m_hasGLContext; + return hasContext; +} + +void TransferQueue::setHasGLContext(bool hasContext) +{ + android::Mutex::Autolock lock(m_hasGLContextLock); + m_hasGLContext = hasContext; +} + +void TransferQueue::discardQueue() +{ + // 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(); + } +} + +// 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(); + + cleanupTransportQueue(); + if (!getHasGLContext()) + setHasGLContext(true); + + // Start from the oldest item, we call the updateTexImage to retrive + // the texture and blit that into each BaseTile's texture. + const int nextItemIndex = getNextTransferQueueIndex(); + int index = nextItemIndex; + for (int k = 0; k < ST_BUFFER_NUMBER ; k++) { + if (m_transferQueue[index].status == pendingBlit) { + bool obsoleteBaseTile = checkObsolete(index); + // Save the needed info, update the Surf Tex, clean up the item in + // the queue. Then either move on to next item or copy the content. + BaseTileTexture* destTexture = 0; + if (!obsoleteBaseTile) + destTexture = m_transferQueue[index].savedBaseTilePtr->texture(); + + 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"); + continue; + } + + blitTileFromQueue(m_fboID, destTexture, + m_sharedSurfaceTextureId, + m_sharedSurfaceTexture->getCurrentTextureTarget()); + + // After the base tile copied into the GL texture, we need to + // update the texture's info such that at draw time, readyFor + // will find the latest texture's info + // We don't need a map any more, each texture contains its own + // texturesTileInfo. + destTexture->setOwnTextureTileInfoFromQueue(&m_transferQueue[index].tileInfo); + + XLOG("Blit tile x, y %d %d to destTexture->m_ownTextureId %d", + m_transferQueue[index].tileInfo.m_x, + m_transferQueue[index].tileInfo.m_y, + destTexture->m_ownTextureId); + } + index = (index + 1) % ST_BUFFER_NUMBER; + } + + 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_transferQueueLock.unlock(); +} + +// 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) +{ + m_transferQueueIndex = index; + + if (m_transferQueue[index].savedBaseTilePtr + || m_transferQueue[index].status != emptyItem) { + XLOG("ERROR update a tile which is dirty already @ index %d", index); + } + + m_transferQueue[index].savedBaseTilePtr = renderInfo->baseTile; + m_transferQueue[index].status = pendingBlit; + + // Now fill the tileInfo. + TextureTileInfo* textureInfo = &m_transferQueue[index].tileInfo; + + textureInfo->m_x = renderInfo->x; + textureInfo->m_y = renderInfo->y; + textureInfo->m_scale = renderInfo->scale; + textureInfo->m_painter = renderInfo->tilePainter; + + textureInfo->m_picture = renderInfo->textureInfo->m_pictureCount; +} + +// Note: this need to be called within th m_transferQueueLock. +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; + + 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; + } + 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() +{ + glGetIntegerv(GL_VIEWPORT, m_GLStateBeforeBlit.viewport); + glGetBooleanv(GL_SCISSOR_TEST, m_GLStateBeforeBlit.scissor); + glGetBooleanv(GL_DEPTH_TEST, m_GLStateBeforeBlit.depth); + glGetFloatv(GL_COLOR_CLEAR_VALUE, m_GLStateBeforeBlit.clearColor); +} + +void TransferQueue::setGLStateForCopy(int width, int height) +{ + // Need to match the texture size. + glViewport(0, 0, width, height); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); +} + +void TransferQueue::restoreGLState() +{ + glViewport(m_GLStateBeforeBlit.viewport[0], + m_GLStateBeforeBlit.viewport[1], + m_GLStateBeforeBlit.viewport[2], + m_GLStateBeforeBlit.viewport[3]); + + if (m_GLStateBeforeBlit.scissor[0]) + glEnable(GL_SCISSOR_TEST); + + if (m_GLStateBeforeBlit.depth) + glEnable(GL_DEPTH_TEST); + + glClearColor(m_GLStateBeforeBlit.clearColor[0], + m_GLStateBeforeBlit.clearColor[1], + m_GLStateBeforeBlit.clearColor[2], + m_GLStateBeforeBlit.clearColor[3]); +} + +int TransferQueue::getNextTransferQueueIndex() +{ + return (m_transferQueueIndex + 1) % ST_BUFFER_NUMBER; +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING diff --git a/Source/WebCore/platform/graphics/android/TransferQueue.h b/Source/WebCore/platform/graphics/android/TransferQueue.h new file mode 100644 index 0000000..e0046c3 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/TransferQueue.h @@ -0,0 +1,126 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TransferQueue_h +#define TransferQueue_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "BaseTile.h" +#include "BaseTileTexture.h" +#include "ShaderProgram.h" +#include "TiledPage.h" + +namespace WebCore { + +struct GLState { + GLint viewport[4]; + GLboolean scissor[1]; + GLboolean depth[1]; + GLfloat clearColor[4]; +}; + +class TransferQueue { +public: + TransferQueue(); + ~TransferQueue(); + + 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 m_ANW; + + bool getHasGLContext(); + void setHasGLContext(bool hasContext); + + int getNextTransferQueueIndex(); + + void addItemInTransferQueue(const TileRenderInfo* info, int index); + + // Check if the item @ index is ready for update. + // The lock will be done when returning true. + bool lockForUpdate(int index, const TileRenderInfo* renderInfo); + + void discardQueue(); + + // Store info for currentOpWaitingRemoval() to tell which operation + // will be removed. + TilePainter* m_currentRemovingPaint; + + // Return the buffer number. + int size(); + +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; + + // GLContext can be lost when WebView destroyed. + bool m_hasGLContext; + android::Mutex m_hasGLContextLock; + + // 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); + + // Before each draw call and the blit operation, clean up all the + // 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); + + // 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; + + sp m_sharedSurfaceTexture; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TransferQueue_h -- cgit v1.1 From 0f948783a942d246d031c37f85805022c76bcc21 Mon Sep 17 00:00:00 2001 From: Teng-Hui Zhu Date: Wed, 3 Aug 2011 10:02:57 -0700 Subject: increase layer tiles limit bug:5069164 Change-Id: Ifbba6d912e20868d0618441b7f497270e1d9f737 --- Source/WebCore/platform/graphics/android/TilesManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 402f4ec..7b1581b 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -75,7 +75,7 @@ #define TILE_HEIGHT 256 #define LAYER_TILE_WIDTH 256 #define LAYER_TILE_HEIGHT 256 -#define LAYER_TILES 10 +#define LAYER_TILES 50 // Define a maximum amount of ram used by layers #define MAX_LAYERS_ALLOCATION 33554432 // 32Mb -- cgit v1.1 From c077c5a819a1187b4789655b3e42323c59630af6 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Fri, 5 Aug 2011 14:05:23 -0700 Subject: Force NativeWindow rendering to use EXTERNAL_OES textures bug:5114637 Allows browser plugin to draw texture correctly Change-Id: Ibd61b11598d0ca5bcff28ed0c92e6f20073f5ad6 --- Source/WebCore/platform/graphics/android/GLUtils.cpp | 15 --------------- Source/WebCore/platform/graphics/android/GLUtils.h | 2 -- Source/WebCore/platform/graphics/android/MediaTexture.cpp | 3 +-- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index 039896e..d1fe51a 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -562,21 +562,6 @@ void GLUtils::createTextureFromEGLImage(GLuint texture, EGLImageKHR image, GLint glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); } -GLenum GLUtils::getTextureTarget(android::SurfaceTexture* surfaceTexture) -{ -#if DEPRECATED_SURFACE_TEXTURE_MODE - if (surfaceTexture) { - GLenum target = surfaceTexture->getCurrentTextureTarget(); - // TODO: remove this translation when TEXTURE_2D+RGBA surface texture - // support is deprecated. - if (target == GL_TEXTURE_2D) - return 0; - return target; - } -#endif - return GL_TEXTURE_2D; -} - } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/android/GLUtils.h b/Source/WebCore/platform/graphics/android/GLUtils.h index 67ff77a..b952513 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.h +++ b/Source/WebCore/platform/graphics/android/GLUtils.h @@ -83,8 +83,6 @@ public: static void updateSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap, GLint filter = GL_LINEAR); #endif static void updateSharedSurfaceTextureWithBitmap(const TileRenderInfo* , int x, int y, const SkBitmap& bitmap); - - static GLenum getTextureTarget(android::SurfaceTexture*); }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp index a653d6e..3fecfb5 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp @@ -105,10 +105,9 @@ void MediaTexture::drawContent(const TransformationMatrix& matrix) m_surfaceTexture->updateTexImage(); bool forceBlending = ANativeWindow_getFormat(m_surfaceTextureClient.get()) == WINDOW_FORMAT_RGB_565; - GLenum target = GLUtils::getTextureTarget(m_surfaceTexture.get()); TilesManager::instance()->shader()->drawLayerQuad(matrix, m_dimensions, m_textureId, 1.0f, - forceBlending, target); + forceBlending, GL_TEXTURE_EXTERNAL_OES); } void MediaTexture::drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds) -- cgit v1.1 From 1b0334615bb368006a7278c011f76af0dedfdf56 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Thu, 11 Aug 2011 11:51:35 -0700 Subject: Fix crash issue with drawing retain layers as needed bug:4177062 Change-Id: Ifd8d493c8ed3b13eedece260136be873f6701fed --- .../platform/graphics/android/LayerAndroid.cpp | 35 +++++++++++++++------- .../platform/graphics/android/LayerAndroid.h | 3 +- .../platform/graphics/android/PaintedSurface.cpp | 8 +++++ .../platform/graphics/android/PaintedSurface.h | 2 ++ .../platform/graphics/android/TilesManager.cpp | 16 +++++++++- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index 97ff692..65e0ec1 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -706,23 +706,38 @@ void LayerAndroid::showLayer(int indent) this->getChild(i)->showLayer(indent + 1); } -void LayerAndroid::assignTexture(LayerAndroid* oldTree) +// We go through our tree, and if we have layer in the new +// tree that is similar, we tranfer our texture to it. +// Otherwise, we remove ourselves from the texture so +// that TilesManager::swapLayersTextures() have a chance +// at deallocating the textures (PaintedSurfaces) +void LayerAndroid::assignTextureTo(LayerAndroid* newTree) { int count = this->countChildren(); for (int i = 0; i < count; i++) - this->getChild(i)->assignTexture(oldTree); + this->getChild(i)->assignTextureTo(newTree); - if (oldTree) { - LayerAndroid* oldLayer = oldTree->findById(uniqueId()); - if (oldLayer == this) + if (newTree) { + LayerAndroid* newLayer = newTree->findById(uniqueId()); + if (newLayer == this) return; - - if (oldLayer && oldLayer->texture()) { - oldLayer->texture()->replaceLayer(this); - m_texture = oldLayer->texture(); - SkSafeRef(m_texture); + if (newLayer && m_texture) { + m_texture->replaceLayer(newLayer); + newLayer->m_texture = m_texture; + SkSafeRef(newLayer->m_texture); + } + if (!newLayer && m_texture) { + m_texture->removeLayer(this); + m_texture = 0; } } +} + +void LayerAndroid::createTexture() +{ + int count = this->countChildren(); + for (int i = 0; i < count; i++) + this->getChild(i)->createTexture(); if (needsTexture() && !m_texture) m_texture = new PaintedSurface(this); diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index c4ed9fe..8ad52e0 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -252,7 +252,8 @@ public: friend LayerAndroid* android::deserializeLayer(SkStream* stream); PaintedSurface* texture() { return m_texture; } - void assignTexture(LayerAndroid* oldTree); + void assignTextureTo(LayerAndroid* newTree); + void createTexture(); protected: virtual void onDraw(SkCanvas*, SkScalar opacity); diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp index fe7044c..fd4475b 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp @@ -60,6 +60,7 @@ void PaintedSurface::removeLayer(LayerAndroid* layer) android::Mutex::Autolock lock(m_layerLock); if (m_layer != layer) return; + SkSafeUnref(m_layer); m_layer = 0; } @@ -72,6 +73,8 @@ void PaintedSurface::replaceLayer(LayerAndroid* layer) if (m_layer && layer->uniqueId() != m_layer->uniqueId()) return; + SkSafeRef(layer); + SkSafeUnref(m_layer); m_layer = layer; } @@ -140,6 +143,7 @@ bool PaintedSurface::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictu { m_layerLock.lock(); LayerAndroid* layer = m_layer; + SkSafeRef(layer); m_layerLock.unlock(); if (!layer) @@ -148,6 +152,7 @@ bool PaintedSurface::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictu layer->contentDraw(canvas); m_pictureUsed = layer->pictureUsed(); *pictureUsed = m_pictureUsed; + SkSafeUnref(layer); return true; } @@ -156,10 +161,13 @@ void PaintedSurface::paintExtra(SkCanvas* canvas) { m_layerLock.lock(); LayerAndroid* layer = m_layer; + SkSafeRef(layer); m_layerLock.unlock(); if (layer) layer->extraDraw(canvas); + + SkSafeUnref(layer); } float PaintedSurface::opacity() { diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h index 84fe64c..6b6c74f 100644 --- a/Source/WebCore/platform/graphics/android/PaintedSurface.h +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h @@ -51,12 +51,14 @@ public: , m_busy(false) { TilesManager::instance()->addPaintedSurface(this); + SkSafeRef(m_layer); #ifdef DEBUG_COUNT ClassTracker::instance()->increment("PaintedSurface"); #endif } virtual ~PaintedSurface() { + SkSafeUnref(m_layer); #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("PaintedSurface"); #endif diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index ba48111..4ada041 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -189,8 +189,22 @@ void TilesManager::resetTextureUsage(TiledPage* page) void TilesManager::swapLayersTextures(LayerAndroid* oldTree, LayerAndroid* newTree) { + if (oldTree) + oldTree->assignTextureTo(newTree); + if (newTree) - newTree->assignTexture(oldTree); + newTree->createTexture(); + + WTF::Vector collect; + for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) { + PaintedSurface* surface = m_paintedSurfaces[i]; + if (!surface->layer()) + collect.append(surface); + } + for (unsigned int i = 0; i < collect.size(); i++) { + m_paintedSurfaces.remove(m_paintedSurfaces.find(collect[i])); + SkSafeUnref(collect[i]); + } } void TilesManager::addPaintedSurface(PaintedSurface* surface) -- cgit v1.1 From ccecaffd26fd14da47da8230eee4f777e63cf0ba Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Thu, 11 Aug 2011 14:06:51 -0700 Subject: Remove ANativeWindow call to avoid blocking call bug:5114637 Determine alpha blending through surface texture instead of ANativeWindow call. Should no longer break the gpl build... Change-Id: Iacc733c29413f0302304b78f378a003d690199f0 --- Source/WebCore/platform/graphics/android/MediaTexture.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp index 3fecfb5..96d136a 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp @@ -104,10 +104,20 @@ void MediaTexture::drawContent(const TransformationMatrix& matrix) m_surfaceTexture->updateTexImage(); - bool forceBlending = ANativeWindow_getFormat(m_surfaceTextureClient.get()) == WINDOW_FORMAT_RGB_565; + sp buf = m_surfaceTexture->getCurrentBuffer(); + + PixelFormat f = buf->getPixelFormat(); + // only attempt to use alpha blending if alpha channel exists + bool forceAlphaBlending = !( + PIXEL_FORMAT_RGBX_8888 == f || + PIXEL_FORMAT_RGB_888 == f || + PIXEL_FORMAT_RGB_565 == f || + PIXEL_FORMAT_RGB_332 == f); + TilesManager::instance()->shader()->drawLayerQuad(matrix, m_dimensions, m_textureId, 1.0f, - forceBlending, GL_TEXTURE_EXTERNAL_OES); + forceAlphaBlending, + GL_TEXTURE_EXTERNAL_OES); } void MediaTexture::drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds) -- cgit v1.1 From ed835a504403ec308ecfbfef4bccb343b01012c4 Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Mon, 29 Aug 2011 13:51:19 -0400 Subject: Fix plugin crashes due to bad ref counting. bug: 5197948 Change-Id: Iece573a141feda56af2123b5fc9ace4cefa5139d --- Source/WebCore/platform/graphics/android/MediaLayer.cpp | 6 +++--- Source/WebCore/platform/graphics/android/MediaLayer.h | 2 +- Source/WebCore/platform/graphics/android/MediaTexture.cpp | 10 ++++++++-- Source/WebCore/platform/graphics/android/MediaTexture.h | 2 +- Source/WebKit/android/plugins/PluginWidgetAndroid.cpp | 12 +++--------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp index ae65173..5625bbe 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp @@ -40,11 +40,11 @@ namespace WebCore { -MediaLayer::MediaLayer(jobject weakWebViewRef) : LayerAndroid((RenderLayer*) NULL) +MediaLayer::MediaLayer(jobject webViewRef) : LayerAndroid((RenderLayer*) NULL) { - m_contentTexture = new MediaTexture(weakWebViewRef); + m_contentTexture = new MediaTexture(webViewRef); m_contentTexture->incStrong(this); - m_videoTexture = new MediaTexture(weakWebViewRef); + m_videoTexture = new MediaTexture(webViewRef); m_videoTexture->incStrong(this); m_isCopy = false; diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.h b/Source/WebCore/platform/graphics/android/MediaLayer.h index dd58674..6d08ed6 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.h +++ b/Source/WebCore/platform/graphics/android/MediaLayer.h @@ -32,7 +32,7 @@ namespace WebCore { class MediaLayer : public LayerAndroid { public: - MediaLayer(jobject weakWebViewRef); + MediaLayer(jobject webViewRef); MediaLayer(const MediaLayer& layer); virtual ~MediaLayer(); diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.cpp b/Source/WebCore/platform/graphics/android/MediaTexture.cpp index 96d136a..eb143a4 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.cpp +++ b/Source/WebCore/platform/graphics/android/MediaTexture.cpp @@ -48,9 +48,15 @@ namespace WebCore { -MediaTexture::MediaTexture(jobject weakWebViewRef) : android::LightRefBase() +MediaTexture::MediaTexture(jobject webViewRef) : android::LightRefBase() { - m_weakWebViewRef = weakWebViewRef; + if (webViewRef) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_weakWebViewRef = env->NewWeakGlobalRef(webViewRef); + } else { + m_weakWebViewRef = 0; + } + m_textureId = 0; m_dimensions.setEmpty(); m_newWindowRequest = false; diff --git a/Source/WebCore/platform/graphics/android/MediaTexture.h b/Source/WebCore/platform/graphics/android/MediaTexture.h index d7ae9cb..c617264 100644 --- a/Source/WebCore/platform/graphics/android/MediaTexture.h +++ b/Source/WebCore/platform/graphics/android/MediaTexture.h @@ -36,7 +36,7 @@ class MediaListener; class MediaTexture : public android::LightRefBase { public: - MediaTexture(jobject weakWebViewRef); + MediaTexture(jobject webViewRef); ~MediaTexture(); void initNativeWindowIfNeeded(); diff --git a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp index 19433ab..c4c31e5 100644 --- a/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp +++ b/Source/WebKit/android/plugins/PluginWidgetAndroid.cpp @@ -45,7 +45,7 @@ #include "android_graphics.h" #include -#define PLUGIN_DEBUG_LOCAL // controls the printing of log messages +//#define PLUGIN_DEBUG_LOCAL // controls the printing of log messages #define DEBUG_EVENTS 0 // logs event contents, return value, and processing time #define DEBUG_VISIBLE_RECTS 0 // temporary debug printfs and fixes @@ -97,9 +97,7 @@ PluginWidgetAndroid::~PluginWidgetAndroid() { } SkSafeUnref(m_flipPixelRef); - - if (m_layer) - m_layer->unref(); + SkSafeUnref(m_layer); } void PluginWidgetAndroid::init(android::WebViewCore* core) { @@ -158,12 +156,8 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { if (model == kOpenGL_ANPDrawingModel && m_layer == 0) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); jobject webview = m_core->getWebViewJavaObject(); - jobject weakWebViewRef = 0; - if (webview) - weakWebViewRef = env->NewWeakGlobalRef(webview); - m_layer = new WebCore::MediaLayer(weakWebViewRef); + m_layer = new WebCore::MediaLayer(webview); } else if (model != kOpenGL_ANPDrawingModel && m_layer != 0) { m_layer->unref(); -- cgit v1.1 From 9d8ad990d4f36baa517aa81b057ae052f1911634 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 6 Sep 2011 14:44:13 -0700 Subject: Fix old textures not being repainted bug:5261488 Tile textures that were reacquired by the same tiles weren't being marked as dirty. Change-Id: Ie5c41ff7a8166e5e48736bdc504b90e8c5512f79 --- Source/WebCore/platform/graphics/android/BaseTileTexture.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index 9db819c..34de9e7 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -214,6 +214,10 @@ bool BaseTileTexture::release(TextureOwner* owner) if (m_owner != owner) return false; + // force readyFor to return false next call (even if texture reaquired by same tile) + m_ownTextureTileInfo.m_x = -1; + m_ownTextureTileInfo.m_y = -1; + m_ownTextureTileInfo.m_scale = 0; if (!m_busy) { m_owner = 0; } else { -- cgit v1.1 From 3a38386b884b7c6470d5bfb9d63bc77744698a31 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Thu, 8 Sep 2011 03:04:22 +0100 Subject: Roll back fix for http://b/issue?id=4203823 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow positioned divs with overflow to scroll. Keeps tidying up that fix for http://b/issue?id=4203823 did and rolls back the functional change. Bug: 5216561ยง Change-Id: I6268bbe880c432c87ca04e68697f66b32b7032d0 --- Source/WebCore/rendering/RenderLayer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp index ce5bf27..904b1b2 100644 --- a/Source/WebCore/rendering/RenderLayer.cpp +++ b/Source/WebCore/rendering/RenderLayer.cpp @@ -2279,11 +2279,8 @@ void RenderLayer::updateScrollInfoAfterLayout() #if ENABLE(ANDROID_OVERFLOW_SCROLL) bool hasOverflowScroll = ((horizontalOverflow && m_hBar) || (verticalOverflow && m_vBar)); if (hasOverflowScroll) { - // Disable Android overflow scroll for positioned RenderBlock. - if (renderer()->isRenderBlock() && renderer()->isPositioned()) - hasOverflowScroll = false; // Disable UI side scrolling for non-readonly textareas. - else if (renderer()->isTextArea() && (!renderer()->node() + if (renderer()->isTextArea() && (!renderer()->node() || !static_cast(renderer()->node())->readOnly())) hasOverflowScroll = false; } -- cgit v1.1 From ab3edbf9489b21b337a378b88850f06fbdd7d8f8 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Thu, 8 Sep 2011 14:09:43 -0700 Subject: Stop layer tile flickering bug:5265207 Don't steal textures with a draw count from last frame to prevent flickering Change-Id: I0a37b2417f0721b150b47920feea9ddb1666ec28 --- .../platform/graphics/android/TilesManager.cpp | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index 2c263e3..8b6566a 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -235,10 +235,11 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) // 1. If a tile isn't owned, break with that one // 2. If we find a tile in the same page with a different scale, // it's old and not visible. Break with that one - // 3. Otherwise, use the least recently prepared tile + // 3. Otherwise, use the least recently prepared tile, but ignoring tiles + // drawn in the last frame to avoid flickering BaseTileTexture* farthestTexture = 0; - unsigned long long oldestDrawCount = ~0; //maximum u64 + unsigned long long oldestDrawCount = getDrawGLCount() - 1; const unsigned int max = availableTexturePool->size(); for (unsigned int i = 0; i < max; i++) { BaseTileTexture* texture = (*availableTexturePool)[i]; @@ -263,16 +264,18 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) } } - TextureOwner* previousOwner = farthestTexture->owner(); - if (farthestTexture && farthestTexture->acquire(owner)) { - if (previousOwner) { - XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu", - owner->isLayerTile() ? "LAYER" : "BASE", - farthestTexture, owner->x(), owner->y(), oldestDrawCount); + if (farthestTexture) { + TextureOwner* previousOwner = farthestTexture->owner(); + if (farthestTexture->acquire(owner)) { + if (previousOwner) { + XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu", + owner->isLayerTile() ? "LAYER" : "BASE", + farthestTexture, owner->x(), owner->y(), oldestDrawCount); + } + + availableTexturePool->remove(availableTexturePool->find(farthestTexture)); + return farthestTexture; } - - availableTexturePool->remove(availableTexturePool->find(farthestTexture)); - return farthestTexture; } XLOG("Couldn't find an available texture for tile %x (%d, %d) out of %d available!!!", -- cgit v1.1 From 3340859901101ff06458197f30ef417805d23283 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Thu, 8 Sep 2011 16:54:13 -0700 Subject: If unlock base layer marks tiles dirty, repaint bug:5278818 Change-Id: I03206bdc5e95743054c361f235e2d94b835a95d1 --- .../platform/graphics/android/BaseLayerAndroid.cpp | 34 +++++++++++++--------- .../WebCore/platform/graphics/android/BaseTile.cpp | 9 ++++-- .../platform/graphics/android/TiledPage.cpp | 13 +++++---- .../WebCore/platform/graphics/android/TiledPage.h | 5 +++- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index 573ad6b..54290cc 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -141,7 +141,10 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, nextTiledPage->setScale(scale); m_glWebViewState->setFutureViewport(viewportTileBounds); m_glWebViewState->lockBaseLayerUpdate(); - nextTiledPage->updateTileState(viewportTileBounds); + + // ignore dirtiness return value since while zooming we repaint regardless + nextTiledPage->updateTileDirtiness(viewportTileBounds); + nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds, TiledPage::VisibleBounds); // Cancel pending paints for the foreground page @@ -212,24 +215,27 @@ bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale, *buffersSwappedPtr = true; } - // If stuff is happening such that we need a redraw, lock updates to the - // base layer, and only then start painting. + bool needsRedraw = scrolling || zooming || !buffersSwapped; - if (needsRedraw) - m_glWebViewState->lockBaseLayerUpdate(); - else + + // if we don't expect to redraw, unlock the invals + if (!needsRedraw) m_glWebViewState->unlockBaseLayerUpdate(); - XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d", - scrolling, zooming, buffersSwapped, needsRedraw); + // if applied invals mark tiles dirty, need to redraw + needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds); - tiledPage->updateTileState(preZoomBounds); + if (needsRedraw) { + // lock and paint what's needed unless we're zooming, since the new + // tiles won't be relevant soon anyway + m_glWebViewState->lockBaseLayerUpdate(); + if (!zooming) + tiledPage->prepare(goingDown, goingLeft, preZoomBounds, + TiledPage::ExpandedBounds); + } - // Only paint new textures if the base layer has been locked, but not if - // we're zooming since the new tiles won't be relevant soon anyway - if (needsRedraw && !zooming) - tiledPage->prepare(goingDown, goingLeft, preZoomBounds, - TiledPage::ExpandedBounds); + XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d", + scrolling, zooming, buffersSwapped, needsRedraw); tiledPage->draw(transparency, preZoomBounds); diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 0a87ffe..8a4c2d5 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -35,12 +35,15 @@ #include -#ifdef DEBUG - #include #include #include +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__) @@ -432,6 +435,8 @@ void BaseTile::paintBitmap() if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty()) m_dirty = true; + XLOG("painted tile %p (%d, %d), dirty=%d", this, x, y, m_dirty); + if (!m_dirty) m_isSwapNeeded = true; } diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index b6a0c47..78140fa 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -202,27 +202,32 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y } } -void TiledPage::updateTileState(const SkIRect& tileBounds) +bool TiledPage::updateTileDirtiness(const SkIRect& tileBounds) { if (!m_glWebViewState || tileBounds.isEmpty()) { m_invalRegion.setEmpty(); m_invalTilesRegion.setEmpty(); - return; + return false; } + bool visibleTileIsDirty = false; for (int x = 0; x < m_baseTileSize; x++) { BaseTile& tile = m_baseTiles[x]; // if the tile is in the dirty region then we must invalidate it - if (m_invalRegion.contains(tile.x(), tile.y())) + if (m_invalRegion.contains(tile.x(), tile.y())) { tile.markAsDirty(m_latestPictureInval, m_invalTilesRegion); + if (tileBounds.contains(tile.x(), tile.y())) + visibleTileIsDirty = true; + } } // clear the invalidated region as all tiles within that region have now // been marked as dirty. m_invalRegion.setEmpty(); m_invalTilesRegion.setEmpty(); + return visibleTileIsDirty; } void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds) @@ -231,8 +236,6 @@ void TiledPage::prepare(bool goingDown, bool goingLeft, const SkIRect& tileBound return; TilesManager::instance()->gatherTextures(); - // update the tiles distance from the viewport - updateTileState(tileBounds); m_scrollingDown = goingDown; int firstTileX = tileBounds.fLeft; diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index 14306eb..946421c 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -68,7 +68,10 @@ public: // prepare the page for display on the screen void prepare(bool goingDown, bool goingLeft, const SkIRect& tileBounds, PrepareBounds bounds); - void updateTileState(const SkIRect& tileBounds); + + // update tiles with inval information, return true if visible ones are + // dirty (and thus repaint needed) + bool updateTileDirtiness(const SkIRect& tileBounds); // check to see if the page is ready for display -- cgit v1.1 From 4de8d7dd547005c76f4b7b7e756286a26a7a6f0c Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Mon, 12 Sep 2011 15:49:36 -0700 Subject: Fix layer tile allocation to be more consistent, less disco bug:5290559 Two major things: * Avoid swapping front/back textures before the textures have been blitted to avoid race condition where blit fails because it doesn't see a back texture * Don't allow a tile to acquire its front texture to paint into, as the acquisition logic doesn't handle this. Change-Id: I84b59396ca9faaf3ddc7c75b6f66e4736bf4c3cf --- .../WebCore/platform/graphics/android/BaseTile.cpp | 19 +++++++++++-------- .../WebCore/platform/graphics/android/BaseTile.h | 9 ++++++++- .../platform/graphics/android/BaseTileTexture.cpp | 1 - .../platform/graphics/android/TilesManager.cpp | 22 +++++++++++++++------- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index 8a4c2d5..dc17a21 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -70,7 +70,7 @@ BaseTile::BaseTile(bool isLayerTile) , m_lastDirtyPicture(0) , m_isTexturePainted(false) , m_isLayerTile(isLayerTile) - , m_isSwapNeeded(false) + , m_swapDrawCount(0) , m_drawCount(0) { #ifdef DEBUG_COUNT @@ -133,7 +133,7 @@ void BaseTile::reserveTexture() android::AutoMutex lock(m_atomicSync); if (texture && m_backTexture != texture) { - m_isSwapNeeded = false; // no longer ready to swap + m_swapDrawCount = 0; // no longer ready to swap m_backTexture = texture; // this is to catch when the front texture is stolen from beneath us. We @@ -240,7 +240,7 @@ bool BaseTile::isTileReady() { // Return true if the tile's most recently drawn texture is up to date android::AutoMutex lock(m_atomicSync); - BaseTileTexture * texture = m_isSwapNeeded ? m_backTexture : m_frontTexture; + BaseTileTexture * texture = m_swapDrawCount ? m_backTexture : m_frontTexture; if (!texture) return false; @@ -435,10 +435,13 @@ void BaseTile::paintBitmap() if (!m_dirtyArea[m_currentDirtyAreaIndex].isEmpty()) m_dirty = true; - XLOG("painted tile %p (%d, %d), dirty=%d", this, x, y, m_dirty); + XLOG("painted tile %p (%d, %d), texture %p, dirty=%d", this, x, y, texture, m_dirty); - if (!m_dirty) - m_isSwapNeeded = true; + if (!m_dirty) { + // swap textures, but WAIT until the next draw call (since we need + // to let GLWebViewState blit them at the beginning of drawGL) + m_swapDrawCount = TilesManager::instance()->getDrawGLCount() + 1; + } } m_atomicSync.unlock(); @@ -459,7 +462,7 @@ void BaseTile::discardTextures() { bool BaseTile::swapTexturesIfNeeded() { android::AutoMutex lock(m_atomicSync); - if (m_isSwapNeeded) { + if (m_swapDrawCount && TilesManager::instance()->getDrawGLCount() >= m_swapDrawCount) { // discard old texture and swap the new one in its place if (m_frontTexture) m_frontTexture->release(this); @@ -467,7 +470,7 @@ bool BaseTile::swapTexturesIfNeeded() { XLOG("%p's frontTexture was %p, now becoming %p", this, m_frontTexture, m_backTexture); m_frontTexture = m_backTexture; m_backTexture = 0; - m_isSwapNeeded = false; + m_swapDrawCount = 0; XLOG("display texture for %d, %d front is now %p, texture is %p", m_x, m_y, m_frontTexture, m_backTexture); return true; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h index 4c9650f..734a3c8 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/BaseTile.h @@ -148,7 +148,14 @@ private: BaseRenderer* m_renderer; bool m_isLayerTile; - bool m_isSwapNeeded; + + // this is set when the back texture is finished painting and should be + // swapped to the front. it is set with the NEXT drawGL call (see + // TilesManager::m_drawGLCount) so that the textures may be blitted at the + // beginning of GLWebViewState::drawGL before they are swapped + + // 4 steps for texture: paint -> blit -> swap -> draw + unsigned long long m_swapDrawCount; // the most recent GL draw before this tile was prepared. used for // prioritization and caching. tiles with old drawcounts and textures they diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index 8cc67b9..f049b6f 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -229,7 +229,6 @@ bool BaseTileTexture::release(TextureOwner* owner) // force readyFor to return false next call (even if texture reaquired by same tile) m_ownTextureTileInfo.m_x = -1; m_ownTextureTileInfo.m_y = -1; - m_ownTextureTileInfo.m_scale = 0; if (!m_busy) { m_owner = 0; } else { diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index bb8feb9..ee35ce2 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -100,7 +100,7 @@ TilesManager::TilesManager() , m_showVisualIndicator(false) , m_invertedScreen(false) , m_invertedScreenSwitch(false) - , m_drawGLCount(0) + , m_drawGLCount(1) { XLOG("TilesManager ctor"); m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION); @@ -268,9 +268,10 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) // The heuristic for selecting a texture is as follows: // 1. If a tile isn't owned, break with that one - // 2. If we find a tile in the same page with a different scale, + // 2. Don't let tiles acquire their front textures + // 3. If we find a tile in the same page with a different scale, // it's old and not visible. Break with that one - // 3. Otherwise, use the least recently prepared tile, but ignoring tiles + // 4. Otherwise, use the least recently prepared tile, but ignoring tiles // drawn in the last frame to avoid flickering BaseTileTexture* farthestTexture = 0; @@ -284,6 +285,11 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) break; } + // Don't let a tile acquire its own front texture, as the acquisition + // logic doesn't handle that + if (currentOwner == owner) + continue; + if (currentOwner->page() == owner->page() && texture->scale() != owner->scale()) { // if we render the back page with one scale, then another while // still zooming, we recycle the tiles with the old scale instead of @@ -300,12 +306,13 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) } if (farthestTexture) { - TextureOwner* previousOwner = farthestTexture->owner(); + BaseTile* previousOwner = static_cast(farthestTexture->owner()); if (farthestTexture->acquire(owner)) { if (previousOwner) { - XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu", + XLOG("%s texture %p stolen from tile %d, %d, drawCount was %llu (current is %llu)", owner->isLayerTile() ? "LAYER" : "BASE", - farthestTexture, owner->x(), owner->y(), oldestDrawCount); + farthestTexture, previousOwner->x(), previousOwner->y(), + oldestDrawCount, getDrawGLCount()); } availableTexturePool->remove(availableTexturePool->find(farthestTexture)); @@ -313,7 +320,8 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) } } - XLOG("Couldn't find an available texture for tile %x (%d, %d) out of %d available!!!", + XLOG("Couldn't find an available texture for %s tile %x (%d, %d) out of %d available", + owner->isLayerTile() ? "LAYER" : "BASE", owner, owner->x(), owner->y(), max); #ifdef DEBUG printTextures(); -- cgit v1.1 From a4723810a9d5f9957a05e568c14ddfe80179cfa9 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Thu, 22 Sep 2011 16:25:22 -0700 Subject: Discard BaseTileTextures entirely when they delete their GL textures bug:5361337 Fixes issue with garbage being drawn in unpainted tiles, and also allocates tiles very lazily. Change-Id: I9799b63670a80748a4809b61506da96a739d3a65 --- Source/WebCore/platform/graphics/android/BaseTileTexture.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index f049b6f..d60d695 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -89,6 +89,7 @@ void BaseTileTexture::discardTexture() { if (m_ownTextureId) GLUtils::deleteTexture(&m_ownTextureId); + release(m_owner); } void BaseTileTexture::destroyTextures(SharedTexture** textures) @@ -274,13 +275,6 @@ void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info bool BaseTileTexture::readyFor(BaseTile* baseTile) { - if (!m_ownTextureId) { - // If our backing opengl texture doesn't exist, allocate it and return - // false since it won't have useful data - requireTexture(); - return false; - } - const TextureTileInfo* info = &m_ownTextureTileInfo; if (info && (info->m_x == baseTile->x()) && -- cgit v1.1 From a120b06edde55ad594c59fcd8e6bbc93021d89d0 Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 12 Oct 2011 14:08:26 -0700 Subject: Revert "Support "Vertical Writing Mode"." This reverts commit 5403113c5aa5d55a05ea001f562829e907632178 --- .../platform/graphics/android/FontAndroid.cpp | 24 +++------------------- .../platform/graphics/android/FontCacheAndroid.cpp | 4 +--- .../graphics/android/FontCustomPlatformData.cpp | 5 ++--- .../platform/graphics/android/FontDataAndroid.cpp | 11 ---------- .../platform/graphics/android/FontPlatformData.h | 11 ++++------ .../graphics/android/FontPlatformDataAndroid.cpp | 22 ++++++-------------- 6 files changed, 16 insertions(+), 61 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp index fd6d41b..6b4296b 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp @@ -183,10 +183,8 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, SkScalar y = SkFloatToScalar(point.y()); const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from); const GlyphBufferAdvance* adv = glyphBuffer.advances(from); - SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs); + SkAutoSTMalloc<32, SkPoint> storage(numGlyphs); SkPoint* pos = storage.get(); - SkPoint* vPosBegin = storage2.get(); - SkPoint* vPosEnd = storage3.get(); SkCanvas* canvas = gc->platformContext()->mCanvas; @@ -223,28 +221,12 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, localCount * sizeof(uint16_t), &pos[localIndex], paint); } else { - bool isVertical = font->platformData().orientation() == Vertical; for (int i = 0; i < numGlyphs; i++) { pos[i].set(x, y); + x += SkFloatToScalar(adv[i].width()); y += SkFloatToScalar(adv[i].height()); - if (isVertical) { - SkScalar myWidth = SkFloatToScalar(adv[i].width()); - vPosBegin[i].set(x + myWidth, y); - vPosEnd[i].set(x + myWidth, y - myWidth); - x += myWidth; - - SkPath path; - path.reset(); - path.moveTo(vPosBegin[i]); - path.lineTo(vPosEnd[i]); - canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint); - } - else { - x += SkFloatToScalar(adv[i].width()); - } } - if (!isVertical) - canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); + canvas->drawPosText(glyphs, numGlyphs * sizeof(uint16_t), pos, paint); } } diff --git a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp index 4fc3b4e..20ffd17 100644 --- a/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontCacheAndroid.cpp @@ -177,9 +177,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD result = new FontPlatformData(tf, fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), - (style & SkTypeface::kItalic) && !tf->isItalic(), - fontDescription.orientation(), - fontDescription.textOrientation()); + (style & SkTypeface::kItalic) && !tf->isItalic()); } tf->unref(); diff --git a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp index 4279ce8..72fac68 100644 --- a/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/android/FontCustomPlatformData.cpp @@ -45,8 +45,7 @@ FontCustomPlatformData::~FontCustomPlatformData() // the unref is enough to release the font data... } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, - FontOrientation fontOrientation, TextOrientation textOrientation, FontWidthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode) { // turn bold/italic into fakeBold/fakeItalic if (m_typeface != NULL) { @@ -55,7 +54,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b if (m_typeface->isItalic() == italic) italic = false; } - return FontPlatformData(m_typeface, size, bold, italic, fontOrientation, textOrientation); + return FontPlatformData(m_typeface, size, bold, italic); } FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) diff --git a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp index c6dd174..1f19b6d 100644 --- a/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontDataAndroid.cpp @@ -32,7 +32,6 @@ #include "SimpleFontData.h" #include "FloatRect.h" #include "FontDescription.h" -#include "SkFontHost.h" #include "SkPaint.h" #include "SkTypeface.h" #include "SkTime.h" @@ -58,16 +57,6 @@ void SimpleFontData::platformInit() m_fontMetrics.setXHeight(SkScalarToFloat(-skiaFontMetrics.fAscent) * 0.56f); // hack I stole from the window's port m_fontMetrics.setLineSpacing(a + d); m_fontMetrics.setLineGap(SkScalarToFloat(skiaFontMetrics.fLeading)); - - if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { - static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a'); - static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G'); - const SkFontID fontID = m_platformData.uniqueID(); - size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag); - size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag); - if ((vheaSize > 0) || (vorgSize > 0)) - m_hasVerticalGlyphs = true; - } } void SimpleFontData::platformCharWidthInit() diff --git a/Source/WebCore/platform/graphics/android/FontPlatformData.h b/Source/WebCore/platform/graphics/android/FontPlatformData.h index 5c3313e..56ce6e9 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/android/FontPlatformData.h @@ -31,7 +31,6 @@ #define FontPlatformData_h #include "FontOrientation.h" -#include "TextOrientation.h" #include #ifndef NDEBUG @@ -53,8 +52,7 @@ public: FontPlatformData(); FontPlatformData(const FontPlatformData&); - FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic, - FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight); + FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic); FontPlatformData(const FontPlatformData& src, float textSize); FontPlatformData(float size, bool syntheticBold, bool syntheticOblique); FontPlatformData(const FontPlatformData& src, SkTypeface* typeface); @@ -67,8 +65,9 @@ public: return mTypeface == hashTableDeletedFontValue(); } - FontOrientation orientation() const { return mOrientation; } - void setOrientation(FontOrientation orientation) { mOrientation = orientation; } + FontOrientation orientation() const { return Horizontal; } // FIXME: Implement. + void setOrientation(FontOrientation) { } // FIXME: Implement. + FontPlatformData& operator=(const FontPlatformData&); bool operator==(const FontPlatformData& a) const; @@ -115,8 +114,6 @@ private: float mTextSize; bool mFakeBold; bool mFakeItalic; - FontOrientation mOrientation; - TextOrientation mTextOrientation; mutable RefPtr m_harfbuzzFace; static SkTypeface* hashTableDeletedFontValue() { diff --git a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp index 1185fa7..8e77b5b 100644 --- a/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontPlatformDataAndroid.cpp @@ -92,17 +92,13 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src) mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; inc_count(); trace(2); } -FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, - FontOrientation orientation, TextOrientation textOrientation) - : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic), - mOrientation(orientation), mTextOrientation(textOrientation) +FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic) + : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); @@ -114,7 +110,7 @@ FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) : mTypeface(src.mTypeface), mTextSize(textSize), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), - m_harfbuzzFace(src.m_harfbuzzFace), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) + m_harfbuzzFace(src.m_harfbuzzFace) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); @@ -133,8 +129,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold), - mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), - mTextOrientation(src.mTextOrientation) + mFakeItalic(src.mFakeItalic) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); @@ -170,8 +165,6 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; - mOrientation = src.mOrientation; - mTextOrientation = src.mTextOrientation; return *this; } @@ -211,9 +204,7 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const return mTypeface == a.mTypeface && mTextSize == a.mTextSize && mFakeBold == a.mFakeBold && - mFakeItalic == a.mFakeItalic && - mOrientation == a.mOrientation && - mTextOrientation == a.mTextOrientation; + mFakeItalic == a.mFakeItalic; } unsigned FontPlatformData::hash() const @@ -228,8 +219,7 @@ unsigned FontPlatformData::hash() const uint32_t sizeAsInt = *reinterpret_cast(&mTextSize); - h ^= 0x01010101 * ((static_cast(mTextOrientation) << 3) | (static_cast(mOrientation) << 2) | - ((int)mFakeBold << 1) | (int)mFakeItalic); + h ^= 0x01010101 * (((int)mFakeBold << 1) | (int)mFakeItalic); h ^= sizeAsInt; return h; } -- cgit v1.1 From c5b87a5d7c7f2ae997a66044b74470ed57878921 Mon Sep 17 00:00:00 2001 From: Nicolas Roard Date: Mon, 14 Nov 2011 09:48:20 -0800 Subject: Use a single shared bitmap instead of one per BaseTile. CL https://android-git.corp.google.com/g/#/c/148708/ uncovered an existing memory leak on BaseTile. As we now keep the bitmap around, this triggers an OOM. We still need to track down the BaseTile leak, but at least with this CL we won't OOM (and it's also using less memory...) bug:5613031 Change-Id: Iac56d3b5c408b5e3e87c0f621e227bd3f4e37c3d --- .../platform/graphics/android/RasterRenderer.cpp | 23 +++++++++++++--------- .../platform/graphics/android/RasterRenderer.h | 2 +- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index 8bf6fcc..0c92de4 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -65,15 +65,20 @@ static const String TAGS[] = { TAG_UPDATE_TEXTURE, }; +SkBitmap* RasterRenderer::g_bitmap = 0; + RasterRenderer::RasterRenderer() : BaseRenderer(BaseRenderer::Raster) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("RasterRenderer"); #endif - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, - TilesManager::instance()->tileWidth(), - TilesManager::instance()->tileHeight()); - m_bitmap.allocPixels(); + if (!g_bitmap) { + g_bitmap = new SkBitmap(); + g_bitmap->setConfig(SkBitmap::kARGB_8888_Config, + TilesManager::instance()->tileWidth(), + TilesManager::instance()->tileHeight()); + g_bitmap->allocPixels(); + } } RasterRenderer::~RasterRenderer() @@ -89,14 +94,14 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can m_perfMon.start(TAG_CREATE_BITMAP); if (renderInfo.baseTile->isLayerTile()) { - m_bitmap.setIsOpaque(false); - m_bitmap.eraseARGB(0, 0, 0, 0); + g_bitmap->setIsOpaque(false); + g_bitmap->eraseARGB(0, 0, 0, 0); } else { - m_bitmap.setIsOpaque(true); - m_bitmap.eraseARGB(255, 255, 255, 255); + g_bitmap->setIsOpaque(true); + g_bitmap->eraseARGB(255, 255, 255, 255); } - SkDevice* device = new SkDevice(NULL, m_bitmap, false); + SkDevice* device = new SkDevice(NULL, *g_bitmap, false); if (renderInfo.measurePerf) { m_perfMon.stop(TAG_CREATE_BITMAP); diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.h b/Source/WebCore/platform/graphics/android/RasterRenderer.h index 69dfaf8..96b3f58 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.h +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.h @@ -52,7 +52,7 @@ protected: virtual const String* getPerformanceTags(int& tagCount); private: - SkBitmap m_bitmap; + static SkBitmap* g_bitmap; }; -- cgit v1.1