diff options
author | Nicolas Roard <nicolasroard@google.com> | 2011-06-21 16:21:55 -0700 |
---|---|---|
committer | Nicolas Roard <nicolasroard@google.com> | 2011-07-14 18:16:39 -0700 |
commit | 3c131605fca8e29a88fdc4923d86bdc3f40adb2b (patch) | |
tree | 440bd04fb01b43ed995348f579e70d668fe52a85 /Source/WebCore/platform/graphics/android | |
parent | 5dcd286d3e3e60f6a090f775a1fdceb40f578b75 (diff) | |
download | external_webkit-3c131605fca8e29a88fdc4923d86bdc3f40adb2b.zip external_webkit-3c131605fca8e29a88fdc4923d86bdc3f40adb2b.tar.gz external_webkit-3c131605fca8e29a88fdc4923d86bdc3f40adb2b.tar.bz2 |
Implements tiled layers. We remove all the existing code in LayerAndroid
related to the old texture management and introduce two new classes:
- PaintedSurface, used as a placeholder ui-side for the regularly
changing LayerAndroid
- TiledTexture, implementing the tiling of PaintedSurface using a set
of BaseTile
bug:4580444 bug:3392331
Change-Id: I0daa079d2acce49f3baa8c312ea0b0dd457ccd5c
Diffstat (limited to 'Source/WebCore/platform/graphics/android')
39 files changed, 1018 insertions, 917 deletions
diff --git a/Source/WebCore/platform/graphics/android/AndroidAnimation.h b/Source/WebCore/platform/graphics/android/AndroidAnimation.h index 6f1410d..68caeb9 100644 --- a/Source/WebCore/platform/graphics/android/AndroidAnimation.h +++ b/Source/WebCore/platform/graphics/android/AndroidAnimation.h @@ -34,7 +34,7 @@ namespace WebCore { class TimingFunction; class AndroidAnimation : public RefCounted<AndroidAnimation> { - public: +public: AndroidAnimation(AnimatedPropertyID type, const Animation* animation, KeyframeValueList* operations, @@ -55,7 +55,7 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> { AnimatedPropertyID type() { return m_type; } bool finished() { return m_finished; } - protected: +protected: double m_beginTime; double m_elapsedTime; double m_duration; @@ -70,7 +70,7 @@ class AndroidAnimation : public RefCounted<AndroidAnimation> { }; class AndroidOpacityAnimation : public AndroidAnimation { - public: +public: static PassRefPtr<AndroidOpacityAnimation> create(const Animation* animation, KeyframeValueList* operations, double beginTime); @@ -84,7 +84,7 @@ class AndroidOpacityAnimation : public AndroidAnimation { }; class AndroidTransformAnimation : public AndroidAnimation { - public: +public: static PassRefPtr<AndroidTransformAnimation> create( const Animation* animation, KeyframeValueList* operations, diff --git a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp index cd19e55..2866ca1 100644 --- a/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/BaseLayerAndroid.cpp @@ -68,10 +68,6 @@ BaseLayerAndroid::BaseLayerAndroid() BaseLayerAndroid::~BaseLayerAndroid() { -#if USE(ACCELERATED_COMPOSITING) - if (TilesManager::hardwareAccelerationEnabled()) - TilesManager::instance()->removeOperationsForBaseLayer(this); -#endif m_content.clear(); #ifdef DEBUG_COUNT ClassTracker::instance()->decrement("BaseLayerAndroid"); @@ -297,6 +293,9 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot, double currentTime = WTF::currentTime(); needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime); + bool goingDown = m_previousVisible.fTop - visibleRect.fTop <= 0; + bool goingLeft = m_previousVisible.fLeft - visibleRect.fLeft >= 0; + m_glWebViewState->setDirection(goingDown, goingLeft); if (!needsRedraw) m_glWebViewState->resetFrameworkInval(); @@ -313,13 +312,6 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot, SkMatrix matrix; matrix.setTranslate(left, top); - // At this point, the previous LayerAndroid* root has been destroyed, - // which will have removed the layers as owners of the textures. - // Let's now do a pass to reserve the textures for the current tree; - // it will only reserve existing textures, not create them on demand. -#ifdef DEBUG - TilesManager::instance()->printLayersTextures("reserve"); -#endif // Get the current scale; if we are zooming, we don't change the scale // factor immediately (see BaseLayerAndroid::drawBasePictureInGL()), but // we change the scaleRequestState. When the state is kReceivedNewScale @@ -330,42 +322,22 @@ bool BaseLayerAndroid::drawGL(LayerAndroid* compositedRoot, if (m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale) { scale = m_glWebViewState->futureScale(); } - bool fullSetup = true; - if ((m_glWebViewState->previouslyUsedRoot() == compositedRoot) && - (compositedRoot->getScale() == scale) && - (!m_glWebViewState->moving())) - fullSetup = false; - compositedRoot->setScale(scale); - if (fullSetup) { - compositedRoot->computeTextureSize(currentTime); - compositedRoot->reserveGLTextures(); - #ifdef DEBUG - int size = compositedRoot->countTextureSize(); - int nbLayers = compositedRoot->nbLayers(); - XLOG("We are using %d Mb for %d layers", size / 1024 / 1024, nbLayers); - compositedRoot->showLayers(); + int size = compositedRoot->countTextureSize(); + int nbLayers = compositedRoot->nbLayers(); + XLOG("We are using %d Mb for %d layers", size / 1024 / 1024, nbLayers); + compositedRoot->showLayers(); #endif - // Now that we marked the textures being used, we delete - // the unnecessary ones to make space... - TilesManager::instance()->cleanupLayersTextures(compositedRoot); - } // Clean up GL textures for video layer. TilesManager::instance()->videoLayerManager()->deleteUnusedTextures(); - // Finally do another pass to create new textures and schedule - // repaints if needed - compositedRoot->createGLTextures(); - if (compositedRoot->drawGL(m_glWebViewState, matrix)) needsRedraw = true; else if (!animsRunning) m_glWebViewState->resetLayersDirtyArea(); - } else { - TilesManager::instance()->cleanupLayersTextures(0); } glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp index f9da6f5..4fde188 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.cpp @@ -62,7 +62,7 @@ void BaseRenderer::drawTileInfo(SkCanvas* canvas, SkPaint paint; char str[256]; snprintf(str, 256, "(%d,%d) %.2f, tl%x p%x c%d", renderInfo.x, renderInfo.y, - renderInfo.scale, this, renderInfo.tiledPage, pictureCount); + renderInfo.scale, this, renderInfo.tilePainter, pictureCount); paint.setARGB(255, 0, 0, 0); canvas->drawText(str, strlen(str), 0, 10, paint); paint.setARGB(255, 255, 0, 0); @@ -104,11 +104,13 @@ int BaseRenderer::renderTiledContent(const TileRenderInfo& renderInfo) setupPartialInval(renderInfo, &canvas); canvas.translate(-renderInfo.x * tileSize.width(), -renderInfo.y * tileSize.height()); canvas.scale(renderInfo.scale, renderInfo.scale); - int pictureCount = renderInfo.tiledPage->paintBaseLayerContent(&canvas); + unsigned int pictureCount = 0; + renderInfo.tilePainter->paint(renderInfo.baseTile, &canvas, &pictureCount); + if (renderInfo.baseTile->isLayerTile()) + renderInfo.tilePainter->paintExtra(&canvas); if (visualIndicator) { canvas.restore(); - const int color = 20 + (pictureCount % 100); // only color the invalidated area diff --git a/Source/WebCore/platform/graphics/android/BaseRenderer.h b/Source/WebCore/platform/graphics/android/BaseRenderer.h index 046634a..0ee9ebd 100644 --- a/Source/WebCore/platform/graphics/android/BaseRenderer.h +++ b/Source/WebCore/platform/graphics/android/BaseRenderer.h @@ -37,7 +37,8 @@ class SkDevice; namespace WebCore { class TextureInfo; -class TiledPage; +class TilePainter; +class BaseTile; struct TileRenderInfo { // coordinates of the tile @@ -53,8 +54,11 @@ struct TileRenderInfo { // the expected size of the tile SkSize tileSize; - // the tiled page that contains the content to be drawn - TiledPage* tiledPage; + // the painter object in charge of drawing our content + TilePainter* tilePainter; + + // the base tile calling us + BaseTile* baseTile; // info about the texture that we are to render into TextureInfo* textureInfo; diff --git a/Source/WebCore/platform/graphics/android/BaseTile.cpp b/Source/WebCore/platform/graphics/android/BaseTile.cpp index ed2ad3e..4cbcf7c 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTile.cpp @@ -53,11 +53,13 @@ namespace WebCore { -BaseTile::BaseTile() +BaseTile::BaseTile(bool isLayerTile) : m_glWebViewState(0) - , m_page(0) + , m_painter(0) , m_x(-1) , m_y(-1) + , m_page(0) + , m_usedLevel(-1) , m_texture(0) , m_scale(1) , m_dirty(true) @@ -65,6 +67,7 @@ BaseTile::BaseTile() , m_usable(true) , m_lastDirtyPicture(0) , m_lastPaintedPicture(0) + , m_isLayerTile(isLayerTile) { #ifdef DEBUG_COUNT ClassTracker::instance()->increment("BaseTile"); @@ -102,12 +105,19 @@ BaseTile::~BaseTile() // All the following functions must be called from the main GL thread. -void BaseTile::setContents(TiledPage* page, int x, int y) +void BaseTile::setContents(TilePainter* painter, int x, int y, float scale) { android::AutoMutex lock(m_atomicSync); - m_page = page; + if ((m_painter != painter) + || (m_x != x) + || (m_y != y) + || (m_scale != scale)) + fullInval(); + + m_painter = painter; m_x = x; m_y = y; + m_scale = scale; } void BaseTile::reserveTexture() @@ -118,8 +128,10 @@ void BaseTile::reserveTexture() if (texture && m_texture != texture) { m_lastPaintedPicture = 0; fullInval(); - m_texture = texture; } + m_texture = texture; + if (m_texture) + m_texture->setUsedLevel(m_usedLevel); } bool BaseTile::removeTexture(BaseTileTexture* texture) @@ -141,15 +153,6 @@ void BaseTile::fullInval() m_dirty = true; } -void BaseTile::setScale(float scale) -{ - android::AutoMutex lock(m_atomicSync); - if (m_scale != scale) { - m_scale = scale; - fullInval(); - } -} - void BaseTile::markAsDirty(int unsigned pictureCount, const SkRegion& dirtyArea) { @@ -189,15 +192,17 @@ void BaseTile::setUsedLevel(int usedLevel) { if (m_texture) m_texture->setUsedLevel(usedLevel); + m_usedLevel = usedLevel; } int BaseTile::usedLevel() { if (m_texture) return m_texture->usedLevel(); - return -1; + return m_usedLevel; } + void BaseTile::draw(float transparency, SkRect& rect, float scale) { if (m_x < 0 || m_y < 0 || m_scale != scale) @@ -232,10 +237,16 @@ void BaseTile::draw(float transparency, SkRect& rect, float scale) } if (m_texture->readyFor(this)) { - XLOG("draw tile %d, %d, %.2f with texture %x", x(), y(), scale, m_texture); - TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, - transparency, - textureInfo->getTextureTarget()); + XLOG("draw tile %x : %d, %d, %.2f with texture %x", this, x(), y(), scale(), m_texture); + if (isLayerTile()) + TilesManager::instance()->shader()->drawLayerQuad(*m_painter->transform(), + rect, textureInfo->m_textureId, + transparency, true, + textureInfo->getTextureTarget()); + else + TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId, + transparency, + textureInfo->getTextureTarget()); } m_texture->consumerRelease(); } @@ -265,7 +276,6 @@ bool BaseTile::isTileReady() // This is called from the texture generation thread void BaseTile::paintBitmap() { - // We acquire the values below atomically. This ensures that we are reading // values correctly across cores. Further, once we have these values they // can be updated by other threads without consequence. @@ -276,15 +286,16 @@ void BaseTile::paintBitmap() float scale = m_scale; const int x = m_x; const int y = m_y; - m_atomicSync.unlock(); + TilePainter* painter = m_painter; - if (!dirty || !texture) + if (!dirty || !texture) { + m_atomicSync.unlock(); return; - - TiledPage* tiledPage = m_page; + } texture->producerAcquireContext(); TextureInfo* textureInfo = texture->producerLock(); + m_atomicSync.unlock(); // at this point we can safely check the ownership (if the texture got // transferred to another BaseTile under us) @@ -301,7 +312,8 @@ void BaseTile::paintBitmap() renderInfo.y = y; renderInfo.scale = scale; renderInfo.tileSize = texture->getSize(); - renderInfo.tiledPage = tiledPage; + renderInfo.tilePainter = painter; + renderInfo.baseTile = this; renderInfo.textureInfo = textureInfo; const float tileWidth = renderInfo.tileSize.width(); @@ -383,7 +395,7 @@ 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(); - texture->setTile(textureInfo, x, y, scale, pictureCount); + texture->setTile(textureInfo, x, y, scale, painter, pictureCount); texture->producerReleaseAndSwap(); if (texture == m_texture) { diff --git a/Source/WebCore/platform/graphics/android/BaseTile.h b/Source/WebCore/platform/graphics/android/BaseTile.h index b5fc7ba..c8873d4 100644 --- a/Source/WebCore/platform/graphics/android/BaseTile.h +++ b/Source/WebCore/platform/graphics/android/BaseTile.h @@ -32,6 +32,7 @@ #include "SkRect.h" #include "SkRegion.h" #include "TextureOwner.h" +#include "TilePainter.h" #include <utils/threads.h> @@ -60,10 +61,13 @@ class GLWebViewState; */ class BaseTile : public TextureOwner { public: - BaseTile(); + BaseTile(bool isLayerTile = false); ~BaseTile(); - void setContents(TiledPage* page, int x, int y); + bool isLayerTile() { return m_isLayerTile; } + + void setContents(TilePainter* painter, int x, int y, float scale); + void setPage(TiledPage* page) { m_page = page; } bool isAvailable() const { return !m_texture; } void reserveTexture(); @@ -74,11 +78,6 @@ public: // the only thread-safe function called by the background thread void paintBitmap(); - int paintPartialBitmap(SkIRect rect, float tx, float ty, - float scale, BaseTileTexture* texture, - TextureInfo* textureInfo, - TiledPage* tiledPage, - bool fullRepaint = false); void markAsDirty(const unsigned int pictureCount, const SkRegion& dirtyArea); @@ -87,7 +86,6 @@ public: void setRepaintPending(bool pending); void setUsable(bool usable); float scale() const { return m_scale; } - void setScale(float scale); void fullInval(); int x() const { return m_x; } @@ -101,16 +99,19 @@ public: virtual bool removeTexture(BaseTileTexture* texture); virtual TiledPage* page() { return m_page; } virtual GLWebViewState* state() { return m_glWebViewState; } + TilePainter* painter() { return m_painter; } private: GLWebViewState* m_glWebViewState; - // these variables are only set when the object is constructed - TiledPage* m_page; + TilePainter* m_painter; int m_x; int m_y; + TiledPage* m_page; + // The remaining variables can be updated throughout the lifetime of the object + int m_usedLevel; BaseTileTexture* m_texture; float m_scale; // used to signal that the that the tile is out-of-date and needs to be redrawn @@ -141,6 +142,8 @@ private: android::Mutex m_atomicSync; BaseRenderer* m_renderer; + + bool m_isLayerTile; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp index f66019a..8419e80 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.cpp @@ -208,7 +208,8 @@ bool BaseTileTexture::release(TextureOwner* owner) } void BaseTileTexture::setTile(TextureInfo* info, int x, int y, - float scale, unsigned int pictureCount) + float scale, TilePainter* painter, + unsigned int pictureCount) { TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); if (!textureInfo) { @@ -217,10 +218,19 @@ void BaseTileTexture::setTile(TextureInfo* info, int x, int y, textureInfo->m_x = x; textureInfo->m_y = y; textureInfo->m_scale = scale; + textureInfo->m_painter = painter; textureInfo->m_picture = pictureCount; m_texturesInfo.set(getWriteableTexture(), textureInfo); } +float BaseTileTexture::scale() +{ + TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); + if (!textureInfo) + return 1.0; + return textureInfo->m_scale; +} + bool BaseTileTexture::readyFor(BaseTile* baseTile) { TextureTileInfo* info = m_texturesInfo.get(getReadableTexture()); @@ -228,6 +238,7 @@ bool BaseTileTexture::readyFor(BaseTile* baseTile) (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())) { return true; } diff --git a/Source/WebCore/platform/graphics/android/BaseTileTexture.h b/Source/WebCore/platform/graphics/android/BaseTileTexture.h index 5496e66..0cdd137 100644 --- a/Source/WebCore/platform/graphics/android/BaseTileTexture.h +++ b/Source/WebCore/platform/graphics/android/BaseTileTexture.h @@ -29,6 +29,7 @@ #include "DoubleBufferedTexture.h" #include "GLWebViewState.h" #include "TextureOwner.h" +#include "TilePainter.h" #include <SkBitmap.h> class SkCanvas; @@ -38,13 +39,14 @@ namespace WebCore { class BaseTile; class TextureTileInfo { - public: +public: TextureTileInfo() : m_x(-1) , m_y(-1) , m_layerId(-1) , m_scale(0) , m_texture(0) + , m_painter(0) , m_picture(0) { } @@ -53,6 +55,7 @@ class TextureTileInfo { int m_layerId; float m_scale; TextureInfo* m_texture; + TilePainter* m_painter; unsigned int m_picture; }; @@ -100,8 +103,10 @@ public: const SkSize& getSize() const { return m_size; } - void setTile(TextureInfo* info, int x, int y, float scale, unsigned int pictureCount); + void setTile(TextureInfo* info, int x, int y, float scale, + TilePainter* painter, unsigned int pictureCount); bool readyFor(BaseTile* baseTile); + float scale(); protected: HashMap<SharedTexture*, TextureTileInfo*> m_texturesInfo; diff --git a/Source/WebCore/platform/graphics/android/ClassTracker.h b/Source/WebCore/platform/graphics/android/ClassTracker.h index 0afde59..e338cbd 100644 --- a/Source/WebCore/platform/graphics/android/ClassTracker.h +++ b/Source/WebCore/platform/graphics/android/ClassTracker.h @@ -35,12 +35,12 @@ namespace WebCore { class ClassTracker { - public: +public: static ClassTracker* instance(); void show(); void increment(String name); void decrement(String name); - private: +private: ClassTracker() {}; HashMap<String, int> m_classes; static ClassTracker* gInstance; diff --git a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h b/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h index 32717a0..f3cb57c 100644 --- a/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h +++ b/Source/WebCore/platform/graphics/android/DeleteTextureOperation.h @@ -32,7 +32,7 @@ namespace WebCore { class DeleteTextureOperation : public QueuedOperation { - public: +public: DeleteTextureOperation(GLuint textureId, EGLImageKHR eglImage) : QueuedOperation(QueuedOperation::DeleteTexture, 0) , m_textureId(textureId) @@ -51,7 +51,7 @@ class DeleteTextureOperation : public QueuedOperation { if (m_eglImage) eglDestroyImageKHR(eglGetCurrentDisplay(), m_eglImage); } - private: +private: GLuint m_textureId; EGLImageKHR m_eglImage; }; diff --git a/Source/WebCore/platform/graphics/android/GLUtils.cpp b/Source/WebCore/platform/graphics/android/GLUtils.cpp index e32f1e9..1f04ff5 100644 --- a/Source/WebCore/platform/graphics/android/GLUtils.cpp +++ b/Source/WebCore/platform/graphics/android/GLUtils.cpp @@ -394,6 +394,11 @@ void GLUtils::updateSurfaceTextureWithBitmap(TextureInfo* texture, int x, int y, int status = ANW->dequeueBuffer(ANW.get(), &anb); checkSurfaceTextureError("dequeueBuffer", status); + if (status != NO_ERROR) { // FIXME: add proper error handling! + native_window_set_buffer_count(ANW.get(), 3); + return; + } + sp<android::GraphicBuffer> buf(new android::GraphicBuffer(anb, false)); status |= ANW->lockBuffer(ANW.get(), buf->getNativeBuffer()); checkSurfaceTextureError("lockBuffer", status); diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp index 199ec01..2832017 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp @@ -33,6 +33,7 @@ #include "GLUtils.h" #include "LayerAndroid.h" #include "TilesManager.h" +#include "TilesTracker.h" #include <wtf/CurrentTime.h> #include <cutils/log.h> @@ -80,6 +81,8 @@ GLWebViewState::GLWebViewState(android::Mutex* buttonMutex) , m_backgroundColor(SK_ColorWHITE) , m_displayRings(false) , m_focusRingTexture(-1) + , m_goingDown(true) + , m_goingLeft(false) { m_viewport.setEmpty(); m_previousViewport.setEmpty(); @@ -109,8 +112,10 @@ GLWebViewState::~GLWebViewState() // will remove any pending operations, and wait if one is underway). delete m_tiledPageA; delete m_tiledPageB; + SkSafeUnref(m_previouslyUsedRoot); SkSafeUnref(m_currentBaseLayer); SkSafeUnref(m_baseLayer); + m_previouslyUsedRoot = 0; m_baseLayer = 0; m_currentBaseLayer = 0; #ifdef DEBUG_COUNT @@ -504,6 +509,10 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, viewport.fRight * scale, viewport.fBottom * scale); +#ifdef DEBUG + TilesManager::instance()->getTilesTracker()->clear(); +#endif + m_baseLayerLock.lock(); BaseLayerAndroid* baseLayer = m_currentBaseLayer; SkSafeRef(baseLayer); @@ -532,7 +541,14 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, if (baseForComposited && baseForComposited->countChildren() >= 1) compositedRoot = static_cast<LayerAndroid*>(baseForComposited->getChild(0)); + if (compositedRoot != m_previouslyUsedRoot) { + TilesManager::instance()->swapLayersTextures(m_previouslyUsedRoot, compositedRoot); + TilesManager::instance()->cleanupTilesTextures(); + } + bool ret = baseLayer->drawGL(compositedRoot, rect, viewport, webViewRect, titleBarHeight, clip, scale, color); + SkSafeRef(compositedRoot); + SkSafeUnref(m_previouslyUsedRoot); m_previouslyUsedRoot = compositedRoot; if (ret) { FloatRect frameworkInval = TilesManager::instance()->shader()->rectInInvScreenCoord(m_frameworkInval); @@ -563,6 +579,9 @@ bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, SkSafeUnref(baseForComposited); SkSafeUnref(baseLayer); +#ifdef DEBUG + TilesManager::instance()->getTilesTracker()->showTrackTextures(); +#endif return ret; } diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.h b/Source/WebCore/platform/graphics/android/GLWebViewState.h index 33a05c6..6834974 100644 --- a/Source/WebCore/platform/graphics/android/GLWebViewState.h +++ b/Source/WebCore/platform/graphics/android/GLWebViewState.h @@ -234,6 +234,13 @@ public: void resetLayersDirtyArea(); LayerAndroid* previouslyUsedRoot() { return m_previouslyUsedRoot; } + bool goingDown() { return m_goingDown; } + bool goingLeft() { return m_goingLeft; } + void setDirection(bool goingDown, bool goingLeft) { + m_goingDown = goingDown; + m_goingLeft = goingLeft; + } + private: void inval(const IntRect& rect); // caller must hold m_baseLayerLock void invalRegion(const SkRegion& region); @@ -291,6 +298,9 @@ private: Vector<IntRect> m_rings; bool m_ringsIsPressed; int m_focusRingTexture; + + bool m_goingDown; + bool m_goingLeft; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp index fc9d85f..6ebe236 100644 --- a/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/GraphicsLayerAndroid.cpp @@ -502,6 +502,7 @@ void GraphicsLayerAndroid::updateScrollingLayers() m_foregroundClipLayer->setMasksToBounds(true); m_foregroundClipLayer->addChild(m_foregroundLayer); m_contentLayer->addChild(m_foregroundClipLayer); + m_contentLayer->setHasOverflowChildren(true); } else { ASSERT(iframeNeedsOverflow && !m_contentLayer->contentIsScrollable()); // No need to copy the children as they will be removed and synced. @@ -866,7 +867,7 @@ void GraphicsLayerAndroid::setContentsToMedia(PlatformLayer* mediaLayer) mediaLayer->setPosition(m_contentLayer->getPosition().fX, m_contentLayer->getPosition().fY); mediaLayer->setSize(m_contentLayer->getWidth(), m_contentLayer->getHeight()); - mediaLayer->setDrawTransform(m_contentLayer->drawTransform()); + mediaLayer->setDrawTransform(*m_contentLayer->drawTransform()); mediaLayer->ref(); m_contentLayer->unref(); diff --git a/Source/WebCore/platform/graphics/android/Layer.cpp b/Source/WebCore/platform/graphics/android/Layer.cpp index 4741397..22c40f1 100644 --- a/Source/WebCore/platform/graphics/android/Layer.cpp +++ b/Source/WebCore/platform/graphics/android/Layer.cpp @@ -22,6 +22,8 @@ Layer::Layer() { fChildrenMatrix.reset(); fFlags = 0; + m_hasOverflowChildren = false; + #ifdef DEBUG_TRACK_NEW_DELETE gLayerAllocCount += 1; SkDebugf("Layer new: %d\n", gLayerAllocCount); @@ -39,6 +41,8 @@ Layer::Layer(const Layer& src) : INHERITED() { fChildrenMatrix = src.fChildrenMatrix; fFlags = src.fFlags; + m_hasOverflowChildren = src.m_hasOverflowChildren; + #ifdef DEBUG_TRACK_NEW_DELETE gLayerAllocCount += 1; SkDebugf("Layer copy: %d\n", gLayerAllocCount); diff --git a/Source/WebCore/platform/graphics/android/Layer.h b/Source/WebCore/platform/graphics/android/Layer.h index 0e2d7d8..6450fde 100644 --- a/Source/WebCore/platform/graphics/android/Layer.h +++ b/Source/WebCore/platform/graphics/android/Layer.h @@ -110,9 +110,13 @@ public: this->draw(canvas, SK_Scalar1); } + void setHasOverflowChildren(bool value) { m_hasOverflowChildren = value; } + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); + bool m_hasOverflowChildren; + private: enum Flags { kInheritFromRootTransform_Flag = 0x01 diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp index cfbbd0d..947a0fc 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -8,7 +8,7 @@ #include "DrawExtra.h" #include "GLUtils.h" #include "MediaLayer.h" -#include "PaintLayerOperation.h" +#include "PaintedSurface.h" #include "ParseCanvas.h" #include "SkBitmapRef.h" #include "SkBounder.h" @@ -42,13 +42,13 @@ namespace WebCore { static int gUniqueId; class OpacityDrawFilter : public SkDrawFilter { - public: +public: OpacityDrawFilter(int opacity) : m_opacity(opacity) { } virtual void filter(SkPaint* paint, Type) { paint->setAlpha(m_opacity); } - private: +private: int m_opacity; }; @@ -66,8 +66,7 @@ LayerAndroid::LayerAndroid(RenderLayer* owner) : Layer(), m_contentsImage(0), m_extra(0), m_uniqueId(++gUniqueId), - m_drawingTexture(0), - m_reservedTexture(0), + m_texture(0), m_pictureUsed(0), m_requestSent(false), m_scale(1), @@ -90,8 +89,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : Layer(layer), m_contentsImage(0), m_extra(0), // deliberately not copied m_uniqueId(layer.m_uniqueId), - m_drawingTexture(0), - m_reservedTexture(0), + m_texture(0), m_requestSent(false), m_owningLayer(layer.m_owningLayer) { @@ -147,8 +145,7 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), m_contentsImage(0), m_extra(0), m_uniqueId(-1), - m_drawingTexture(0), - m_reservedTexture(0), + m_texture(0), m_requestSent(false), m_scale(1), m_lastComputeTextureSize(0), @@ -163,40 +160,10 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : Layer(), #endif } -bool LayerAndroid::removeTexture(BaseTileTexture* aTexture) -{ - LayerTexture* texture = static_cast<LayerTexture*>(aTexture); - android::AutoMutex lock(m_atomicSync); - - bool textureReleased = true; - if (!texture) { // remove ourself from both textures - if (m_drawingTexture) - textureReleased &= m_drawingTexture->release(this); - if (m_reservedTexture && - m_reservedTexture != m_drawingTexture) - textureReleased &= m_reservedTexture->release(this); - } else { - if (m_drawingTexture && m_drawingTexture == texture) - textureReleased &= m_drawingTexture->release(this); - if (m_reservedTexture && - m_reservedTexture == texture && - m_reservedTexture != m_drawingTexture) - textureReleased &= m_reservedTexture->release(this); - } - if (m_drawingTexture && - ((m_drawingTexture->owner() != this) || - (m_drawingTexture->delayedReleaseOwner() == this))) - m_drawingTexture = 0; - if (m_reservedTexture && - ((m_reservedTexture->owner() != this) || - (m_reservedTexture->delayedReleaseOwner() == this))) - m_reservedTexture = 0; - return textureReleased; -} - LayerAndroid::~LayerAndroid() { - removeTexture(0); + if (m_texture) + m_texture->removeLayer(this); removeChildren(); delete m_extra; delete m_contentsImage; @@ -252,7 +219,7 @@ void LayerAndroid::addDirtyArea(GLWebViewState* glWebViewState) { IntSize layerSize(getSize().width(), getSize().height()); - FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(drawTransform(), layerSize); + FloatRect area = TilesManager::instance()->shader()->rectInInvScreenCoord(m_drawTransform, layerSize); FloatRect clip = TilesManager::instance()->shader()->convertScreenCoordToInvScreenCoord(m_clippingRect); area.intersect(clip); @@ -609,7 +576,7 @@ void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, -anchorPointZ()); setDrawTransform(localMatrix); - m_zValue = TilesManager::instance()->shader()->zValue(drawTransform(), getSize().width(), getSize().height()); + m_zValue = TilesManager::instance()->shader()->zValue(m_drawTransform, getSize().width(), getSize().height()); opacity *= getOpacity(); setDrawOpacity(opacity); @@ -617,7 +584,7 @@ void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, if (m_haveClip) { // The clipping rect calculation and intersetion will be done in Screen Coord now. FloatRect clip = - TilesManager::instance()->shader()->rectInScreenCoord(drawTransform(), layerSize); + TilesManager::instance()->shader()->rectInScreenCoord(m_drawTransform, layerSize); clip.intersect(clipping); setDrawClip(clip); } else { @@ -625,7 +592,7 @@ void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, } if (!m_backfaceVisibility - && drawTransform().inverse().m33() < 0) { + && m_drawTransform.inverse().m33() < 0) { setVisible(false); return; } else { @@ -680,262 +647,37 @@ void LayerAndroid::setContentsImage(SkBitmapRef* img) bool LayerAndroid::needsTexture() { return m_contentsImage || (prepareContext() - && m_recordingPicture->width() && m_recordingPicture->height()); + && m_recordingPicture->width() && m_recordingPicture->height() && !m_hasOverflowChildren); } IntRect LayerAndroid::clippedRect() const { IntRect r(0, 0, getWidth(), getHeight()); - IntRect tr = drawTransform().mapRect(r); + IntRect tr = m_drawTransform.mapRect(r); IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr); - IntRect rect = drawTransform().inverse().mapRect(cr); + IntRect rect = m_drawTransform.inverse().mapRect(cr); return rect; } -bool LayerAndroid::outsideViewport() -{ - return m_layerTextureRect.width() == 0 && - m_layerTextureRect.height() == 0; -} - -int LayerAndroid::fullTextureSize() const -{ - return getWidth() * m_scale * getHeight() * m_scale * 4; -} - -int LayerAndroid::clippedTextureSize() const -{ - IntRect cr = clippedRect(); - return cr.width() * cr.height() * 4; -} - -int LayerAndroid::countTextureSize() -{ - int size = clippedTextureSize(); - int count = this->countChildren(); - for (int i = 0; i < count; i++) - size += getChild(i)->countTextureSize(); - return size; -} - -int LayerAndroid::nbLayers() -{ - int nb = 1; - int count = this->countChildren(); - for (int i = 0; i < count; i++) - nb += getChild(i)->nbLayers(); - return nb; -} - -void LayerAndroid::collect(Vector<LayerAndroid*>& layers, int& size) -{ - m_layerTextureRect = clippedRect(); - if (!outsideViewport()) { - layers.append(this); - size += fullTextureSize(); - } - int count = this->countChildren(); - for (int i = 0; i < count; i++) - getChild(i)->collect(layers, size); -} - -static inline bool compareLayerFullSize(const LayerAndroid* a, const LayerAndroid* b) -{ - const int sizeA = a->fullTextureSize(); - const int sizeB = b->fullTextureSize(); - return sizeA > sizeB; -} - -void LayerAndroid::computeTextureSize(double time) -{ - if (m_lastComputeTextureSize + s_computeTextureDelay > time) - return; - m_lastComputeTextureSize = time; - - // First, we collect the layers, computing m_layerTextureRect - // as being clipped against the viewport - Vector <LayerAndroid*> layers; - int total = 0; - collect(layers, total); - - // Then we sort them by the size the full texture would need - std::stable_sort(layers.begin(), layers.end(), compareLayerFullSize); - - // Now, let's determinate which layer can use a full texture - int max = TilesManager::instance()->maxLayersAllocation(); - int maxLayerSize = TilesManager::instance()->maxLayerAllocation(); - XLOG("*** layers sorted by size ***"); - XLOG("total memory needed: %d bytes (%d Mb), max %d Mb", - total, total / 1024 / 1024, max / 1024 / 1024); - for (unsigned int i = 0; i < layers.size(); i++) { - LayerAndroid* layer = layers[i]; - bool clipped = true; - // If we are under the maximum, and the layer inspected - // needs a texture less than the maxLayerSize, use the full texture. - if ((total < max) && - (layer->fullTextureSize() < maxLayerSize) && - (layer->getWidth() * m_scale < TilesManager::instance()->getMaxTextureSize()) && - (layer->getHeight() * m_scale < TilesManager::instance()->getMaxTextureSize())) { - IntRect full(0, 0, layer->getWidth(), layer->getHeight()); - layer->m_layerTextureRect = full; - clipped = false; - } else { - // Otherwise, the layer is clipped; update the total - total -= layer->fullTextureSize(); - total += layer->clippedTextureSize(); - } - XLOG("Layer %d (%.2f, %.2f) %d bytes (clipped: %s)", - layer->uniqueId(), layer->getWidth(), layer->getHeight(), - layer->fullTextureSize(), - clipped ? "YES" : "NO"); - } - XLOG("total memory used after clipping: %d bytes (%d Mb), max %d Mb", - total, total / 1024 / 1024, max / 1024 / 1024); - XLOG("*** end of sorted layers ***"); -} - -void LayerAndroid::showLayers(int indent) -{ - IntRect cr = clippedRect(); - int size = cr.width() * cr.height() * 4; - - char space[256]; - int p = 0; - for (; p < indent; p++) - space[p] = ' '; - space[p] = '\0'; - - bool outside = outsideViewport(); - if (needsTexture() && !outside) { - XLOGC("%s Layer %d (%.2f, %.2f), cropped to (%d, %d, %d, %d), using %d Mb", - space, uniqueId(), getWidth(), getHeight(), - cr.x(), cr.y(), cr.width(), cr.height(), size / 1024 / 1024); - } else if (needsTexture() && outside) { - XLOGC("%s Layer %d is outside the viewport", space, uniqueId()); - } else { - XLOGC("%s Layer %d has no texture", space, uniqueId()); - } - - int count = this->countChildren(); - for (int i = 0; i < count; i++) - getChild(i)->showLayers(indent + 1); -} - -void LayerAndroid::reserveGLTextures() +void LayerAndroid::assignTexture(LayerAndroid* oldTree) { int count = this->countChildren(); for (int i = 0; i < count; i++) - this->getChild(i)->reserveGLTextures(); + this->getChild(i)->assignTexture(oldTree); - if (!needsTexture()) - return; - - if (outsideViewport()) - return; - - LayerTexture* reservedTexture = 0; - reservedTexture = TilesManager::instance()->getExistingTextureForLayer( - this, m_layerTextureRect); - - // If we do not have a drawing texture (i.e. new LayerAndroid tree), - // we get any one available. - if (!m_drawingTexture) { - LayerTexture* texture = reservedTexture; - m_drawingTexture = - TilesManager::instance()->getExistingTextureForLayer( - this, m_layerTextureRect, true, texture); - - if (!m_drawingTexture) - m_drawingTexture = reservedTexture; - } - - // SMP flush - android::AutoMutex lock(m_atomicSync); - // we set the reservedTexture if it's different from the drawing texture - if (m_reservedTexture != reservedTexture && - ((reservedTexture != m_drawingTexture) || - (m_reservedTexture == 0 && m_drawingTexture == 0))) { - // Call release on the reserved texture if it is not the same as the - // drawing texture. - if (m_reservedTexture && (m_reservedTexture != m_drawingTexture)) - m_reservedTexture->release(this); - m_reservedTexture = reservedTexture; - } -} - -void LayerAndroid::createGLTextures() -{ - int count = this->countChildren(); - for (int i = 0; i < count; i++) - this->getChild(i)->createGLTextures(); + if (oldTree) { + LayerAndroid* oldLayer = oldTree->findById(uniqueId()); + if (oldLayer == this) + return; - if (!needsTexture()) - return; - - if (outsideViewport()) - return; - - if (m_drawingTexture && !needsScheduleRepaint(m_drawingTexture)) - return; - - LayerTexture* reservedTexture = m_reservedTexture; - if (!reservedTexture) - reservedTexture = TilesManager::instance()->createTextureForLayer(this, m_layerTextureRect); - - if (!reservedTexture) - return; - - // SMP flush - m_atomicSync.lock(); - m_reservedTexture = reservedTexture; - m_atomicSync.unlock(); - - if (reservedTexture && - reservedTexture->ready() && - (reservedTexture != m_drawingTexture)) { - if (m_drawingTexture) { - TilesManager::instance()->removeOperationsForTexture(m_drawingTexture); - m_drawingTexture->release(this); + if (oldLayer && oldLayer->texture()) { + oldLayer->texture()->replaceLayer(this); + m_texture = oldLayer->texture(); } - m_drawingTexture = reservedTexture; } - if (!needsScheduleRepaint(reservedTexture)) - return; - - m_atomicSync.lock(); - if (!m_requestSent) { - m_requestSent = true; - m_atomicSync.unlock(); - XLOG("We schedule a paint for layer %d (%x), because m_dirty %d, using texture %x (%d, %d)", - uniqueId(), this, m_dirty, m_reservedTexture, - m_reservedTexture->rect().width(), m_reservedTexture->rect().height()); - PaintLayerOperation* operation = new PaintLayerOperation(this); - TilesManager::instance()->scheduleOperation(operation); - } else { - XLOG("We don't schedule a paint for layer %d (%x), because we already sent a request", - uniqueId(), this); - m_atomicSync.unlock(); - } -} - -bool LayerAndroid::needsScheduleRepaint(LayerTexture* texture) -{ - if (!texture) - return false; - - if (!texture->ready()) { - m_dirty = true; - return true; - } - - TextureInfo* textureInfo = texture->consumerLock(); - if (!texture->readyFor(this) || - (texture->rect() != m_layerTextureRect)) - m_dirty = true; - texture->consumerRelease(); - - return m_dirty; + if (needsTexture() && !m_texture) + m_texture = new PaintedSurface(this); } static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b) @@ -949,34 +691,18 @@ bool LayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) if (!m_visible) return false; - if (m_drawingTexture) { - TextureInfo* textureInfo = m_drawingTexture->consumerLock(); - bool ready = m_drawingTexture->readyFor(this); - if (textureInfo && (!m_contentsImage || (ready && m_contentsImage))) { - SkRect bounds; - bounds.set(m_drawingTexture->rect()); - XLOG("LayerAndroid %d %x (%.2f, %.2f) drawGL (texture %x, %f, %f, %f, %f)", - uniqueId(), this, getWidth(), getHeight(), - m_drawingTexture, bounds.fLeft, bounds.fTop, - bounds.width(), bounds.height()); - //TODO determine when drawing if the alpha value is used. - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), bounds, - textureInfo->m_textureId, - m_drawOpacity, true, - textureInfo->getTextureTarget()); - } - if (!ready) - m_dirty = true; - m_drawingTexture->consumerRelease(); - } else if (needsTexture()) { - m_dirty = true; + bool askPaint = false; + + if (m_texture) { + m_texture->prepare(glWebViewState); + askPaint |= m_texture->draw(); } // When the layer is dirty, the UI thread should be notified to redraw. - bool askPaint = drawChildrenGL(glWebViewState, matrix); + askPaint = drawChildrenGL(glWebViewState, matrix); m_atomicSync.lock(); askPaint |= m_dirty; - if ((m_dirty && needsTexture()) || m_hasRunningAnimations || drawTransform().hasPerspective()) + if ((m_dirty && needsTexture()) || m_hasRunningAnimations || m_drawTransform.hasPerspective()) addDirtyArea(glWebViewState); m_atomicSync.unlock(); @@ -1014,84 +740,6 @@ void LayerAndroid::setScale(float scale) m_scale = scale; } -// This is called from the texture generation thread -void LayerAndroid::paintBitmapGL() -{ - // We acquire the values below atomically. This ensures that we are reading - // values correctly across cores. Further, once we have these values they - // can be updated by other threads without consequence. - m_atomicSync.lock(); - LayerTexture* texture = m_reservedTexture; - - if (!texture) { - m_atomicSync.unlock(); - XLOG("Layer %d doesn't have a texture!", uniqueId()); - return; - } - - XLOG("LayerAndroid %d paintBitmapGL, texture used %x (%d, %d)", uniqueId(), texture, - texture->rect().width(), texture->rect().height()); - - // We need to mark the texture as busy before relinquishing the lock - // -- so that TilesManager::cleanupLayersTextures() can check if the texture - // is used before trying to destroy it - // If LayerAndroid::removeTexture() is called before us, we'd have bailed - // out early as texture would have been null; if it is called after us, we'd - // have marked the texture has being busy, and the texture will not be - // destroyed immediately. - texture->producerAcquireContext(); - TextureInfo* textureInfo = texture->producerLock(); - m_atomicSync.unlock(); - - // at this point we can safely check the ownership (if the texture got - // transferred to another BaseTile under us) - if (texture->owner() != this) { - texture->producerRelease(); - return; - } - - XLOG("LayerAndroid %d %x (%.2f, %.2f) paintBitmapGL WE ARE PAINTING", uniqueId(), this, getWidth(), getHeight()); - - SkBitmap bitmap; - bitmap.setConfig(SkBitmap::kARGB_8888_Config, texture->getSize().width(), texture->getSize().height()); - bitmap.allocPixels(); - - SkCanvas canvas(bitmap); - canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); - - float scale = texture->scale(); - - IntRect textureRect = texture->rect(); - - - if (m_contentsImage) { - contentDraw(&canvas); - } else { - SkPicture picture; - SkCanvas* nCanvas = picture.beginRecording(textureRect.width(), - textureRect.height()); - nCanvas->scale(scale, scale); - nCanvas->translate(-textureRect.x(), -textureRect.y()); - contentDraw(nCanvas); - picture.endRecording(); - picture.draw(&canvas); - } - extraDraw(&canvas); - - m_atomicSync.lock(); - texture->setTextureInfoFor(this); - - m_dirty = false; - m_requestSent = false; - - XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId()); - texture->producerUpdate(textureInfo, bitmap); - - m_atomicSync.unlock(); - - XLOG("LayerAndroid %d paintBitmapGL UPDATING DONE", uniqueId()); -} - void LayerAndroid::extraDraw(SkCanvas* canvas) { m_atomicSync.lock(); @@ -1324,7 +972,7 @@ void LayerAndroid::dumpLayers(FILE* file, int indentLevel) const writePoint(file, indentLevel + 1, "position", getPosition()); writePoint(file, indentLevel + 1, "anchor", getAnchorPoint()); - writeMatrix(file, indentLevel + 1, "drawMatrix", drawTransform()); + writeMatrix(file, indentLevel + 1, "drawMatrix", m_drawTransform); writeMatrix(file, indentLevel + 1, "transformMatrix", m_transform); writeRect(file, indentLevel + 1, "clippingRect", SkRect(m_clippingRect)); @@ -1404,6 +1052,7 @@ void LayerAndroid::setExtra(DrawExtra* extra) m_recordingPicture->height()); extra->draw(canvas, this, &dummy); m_extra->endRecording(); + needsRepaint(); } } diff --git a/Source/WebCore/platform/graphics/android/LayerAndroid.h b/Source/WebCore/platform/graphics/android/LayerAndroid.h index bd6c0ef..15c7e0f 100644 --- a/Source/WebCore/platform/graphics/android/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/LayerAndroid.h @@ -24,9 +24,10 @@ #include "FloatRect.h" #include "GraphicsLayerClient.h" #include "Layer.h" -#include "LayerTexture.h" #include "RefPtr.h" +#include "SkBitmap.h" #include "SkColor.h" +#include "SkStream.h" #include "TextureOwner.h" #include "TransformationMatrix.h" @@ -45,10 +46,14 @@ class SkCanvas; class SkMatrix; class SkPicture; +namespace WebCore { +class LayerAndroid; +} + namespace android { class DrawExtra; -void serializeLayer(LayerAndroid* layer, SkWStream* stream); -LayerAndroid* deserializeLayer(SkStream* stream); +void serializeLayer(WebCore::LayerAndroid* layer, SkWStream* stream); +WebCore::LayerAndroid* deserializeLayer(SkStream* stream); } using namespace android; @@ -88,19 +93,15 @@ class BaseTileTexture; class LayerAndroidFindState; class RenderLayer; class TiledPage; +class PaintedSurface; -class LayerAndroid : public Layer, public TextureOwner { - +class LayerAndroid : public Layer { public: LayerAndroid(RenderLayer* owner); LayerAndroid(const LayerAndroid& layer); LayerAndroid(SkPicture*); virtual ~LayerAndroid(); - // TextureOwner methods - virtual bool removeTexture(BaseTileTexture* texture); - - LayerTexture* texture() { return m_reservedTexture; } virtual TiledPage* page() { return 0; } virtual GLWebViewState* state() { return 0; } @@ -111,33 +112,16 @@ public: IntRect clippedRect() const; bool outsideViewport(); - // Debug/info functions - int countTextureSize(); - int nbLayers(); - void showLayers(int indent = 0); - - // Texture size functions - void computeTextureSize(double time); - void collect(Vector<LayerAndroid*>& layers, - int& size); - int clippedTextureSize() const; - int fullTextureSize() const; - - // called on the root layer - void reserveGLTextures(); - void createGLTextures(); - virtual bool needsTexture(); - bool needsScheduleRepaint(LayerTexture* texture); void setScale(float scale); float getScale() { return m_scale; } virtual bool drawGL(GLWebViewState*, SkMatrix&); bool drawChildrenGL(GLWebViewState*, SkMatrix&); - virtual void paintBitmapGL(); void updateGLPositions(const TransformationMatrix& parentMatrix, const FloatRect& clip, float opacity); void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } + float drawOpacity() { return m_drawOpacity; } void setVisible(bool value) { m_visible = value; } bool preserves3D() { return m_preserves3D; } @@ -145,7 +129,7 @@ public: void setAnchorPointZ(float z) { m_anchorPointZ = z; } float anchorPointZ() { return m_anchorPointZ; } void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } - const TransformationMatrix& drawTransform() const { return m_drawTransform; } + const TransformationMatrix* drawTransform() const { return &m_drawTransform; } void setChildrenTransform(const TransformationMatrix& t) { m_childrenTransform = t; } void setDrawClip(const FloatRect& rect) { m_clippingRect = rect; } const FloatRect& drawClip() { return m_clippingRect; } @@ -262,9 +246,14 @@ public: friend void android::serializeLayer(LayerAndroid* layer, SkWStream* stream); friend LayerAndroid* android::deserializeLayer(SkStream* stream); + PaintedSurface* texture() { return m_texture; } + void assignTexture(LayerAndroid* oldTree); + protected: virtual void onDraw(SkCanvas*, SkScalar opacity); + TransformationMatrix m_drawTransform; + private: class FindState; #if DUMP_NAV_CACHE @@ -331,23 +320,12 @@ private: float m_zValue; - TransformationMatrix m_drawTransform; FloatRect m_clippingRect; SkPicture* m_extra; int m_uniqueId; - // We have two textures pointers -- one if the texture we are currently - // using to draw (m_drawingTexture), the other one is the one we get - // from trying to reserve a texture from the TilesManager. Usually, they - // are identical, but in some cases they are not (different scaling - // resulting in the need for different geometry, at initilisation, and - // if the texture asked does not fit in memory) - LayerTexture* m_drawingTexture; - LayerTexture* m_reservedTexture; - - // rect used to query TilesManager for the right texture - IntRect m_layerTextureRect; + PaintedSurface* m_texture; // used to signal that the tile is out-of-date and needs to be redrawn bool m_dirty; diff --git a/Source/WebCore/platform/graphics/android/MediaLayer.cpp b/Source/WebCore/platform/graphics/android/MediaLayer.cpp index 3d1fe12..42bb7d4 100644 --- a/Source/WebCore/platform/graphics/android/MediaLayer.cpp +++ b/Source/WebCore/platform/graphics/android/MediaLayer.cpp @@ -100,7 +100,7 @@ bool MediaLayer::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) // check to see if we need to create a video texture m_videoTexture->initNativeWindowIfNeeded(); // draw any video content if present - m_videoTexture->drawVideo(drawTransform(), mediaBounds); + m_videoTexture->drawVideo(m_drawTransform, mediaBounds); // draw the primary content if (m_bufferedTexture) { @@ -108,7 +108,7 @@ bool MediaLayer::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) if (textureInfo && textureInfo->m_width != 0 && textureInfo->m_height != 0) { // the layer's shader draws the content inverted so we must undo // that change in the transformation matrix - TransformationMatrix m = drawTransform(); + TransformationMatrix m = m_drawTransform; if (!m_isContentInverted) { m.flipY(); m.translate(0, -getSize().height()); diff --git a/Source/WebCore/platform/graphics/android/PaintLayerOperation.cpp b/Source/WebCore/platform/graphics/android/PaintLayerOperation.cpp deleted file mode 100644 index c1ac865..0000000 --- a/Source/WebCore/platform/graphics/android/PaintLayerOperation.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2010, 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 "PaintLayerOperation.h" - -#include "LayerAndroid.h" - -bool PaintLayerOperation::operator==(const QueuedOperation* operation) -{ - if (operation->type() != type()) - return false; - const PaintLayerOperation* op = static_cast<const PaintLayerOperation*>(operation); - return op->m_layer->uniqueId() == m_layer->uniqueId(); -} - -void PaintLayerOperation::run() -{ - if (m_layer) - m_layer->paintBitmapGL(); -} - -Layer* PaintLayerOperation::baseLayer() -{ - if (!m_layer) - return 0; - - return m_layer->getRootLayer(); -} - -LayerTexture* PaintLayerOperation::texture() -{ - if (!m_layer) - return 0; - return m_layer->texture(); -} - -bool PaintLayerBaseFilter::check(QueuedOperation* operation) -{ - if (operation->type() == QueuedOperation::PaintLayer) { - PaintLayerOperation* op = static_cast<PaintLayerOperation*>(operation); - if (op->baseLayer() == m_baseLayer) - return true; - } - return false; -} - -bool PaintLayerTextureFilter::check(QueuedOperation* operation) -{ - if (operation->type() == QueuedOperation::PaintLayer) { - PaintLayerOperation* op = static_cast<PaintLayerOperation*>(operation); - if (op->texture() == m_texture) - return true; - } - return false; -} diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp index 222b69b..8abd250 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.cpp @@ -65,6 +65,10 @@ int PaintTileOperation::priority() { if (!m_tile || m_tile->usedLevel() < 0) return -1; + + if (m_tile->isLayerTile()) + return 25; // for now, use a constant value. + bool goingDown = m_tile->page()->scrollingDown(); SkIRect *rect = m_tile->page()->expandedTileBounds(); int firstTileX = rect->fLeft; diff --git a/Source/WebCore/platform/graphics/android/PaintTileOperation.h b/Source/WebCore/platform/graphics/android/PaintTileOperation.h index 0920f32..f5c73f5 100644 --- a/Source/WebCore/platform/graphics/android/PaintTileOperation.h +++ b/Source/WebCore/platform/graphics/android/PaintTileOperation.h @@ -31,17 +31,52 @@ namespace WebCore { class PaintTileOperation : public QueuedOperation { - public: +public: PaintTileOperation(BaseTile* tile); virtual ~PaintTileOperation(); virtual bool operator==(const QueuedOperation* operation); virtual void run(); virtual int priority(); + TilePainter* painter() { return m_tile->painter(); } + float scale() { return m_tile->scale(); } - private: +private: BaseTile* m_tile; }; +class ScaleFilter : public OperationFilter { +public: + ScaleFilter(float scale) : m_scale(scale) {} + virtual bool check(QueuedOperation* operation) + { + if (operation->type() == QueuedOperation::PaintTile) { + PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); + if (op->scale() != m_scale) + return true; + } + return false; + } +private: + float m_scale; +}; + + +class TilePainterFilter : public OperationFilter { +public: + TilePainterFilter(TilePainter* painter) : m_painter(painter) {} + virtual bool check(QueuedOperation* operation) + { + if (operation->type() == QueuedOperation::PaintTile) { + PaintTileOperation* op = static_cast<PaintTileOperation*>(operation); + if (op->painter() == m_painter) + return true; + } + return false; + } +private: + TilePainter* m_painter; +}; + } #endif // PaintTileSetOperation_h diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.cpp b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp new file mode 100644 index 0000000..a364392 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.cpp @@ -0,0 +1,162 @@ +/* + * 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 "PaintedSurface.h" + +#include "LayerAndroid.h" +#include "TilesManager.h" +#include "SkCanvas.h" +#include "SkPicture.h" + +#ifdef DEBUG + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +void PaintedSurface::removeLayer(LayerAndroid* layer) +{ + if (m_layer != layer) + return; + m_layer = 0; +} + +void PaintedSurface::replaceLayer(LayerAndroid* layer) +{ + if (!layer) + return; + + if (m_layer && layer->uniqueId() != m_layer->uniqueId()) + return; + + m_layer = layer; +} + +void PaintedSurface::prepare(GLWebViewState* state) +{ + if (!m_layer) + return; + + if (!m_layer->needsTexture()) + return; + + XLOG("prepare layer %d %x at scale %.2f", + m_layer->uniqueId(), m_layer, + m_layer->getScale()); + + float scale = m_layer->getScale(); + int w = m_layer->getSize().width(); + int h = m_layer->getSize().height(); + + if (w != m_area.width()) + m_area.setWidth(w); + + if (h != m_area.height()) + m_area.setHeight(h); + + computeVisibleArea(); + + if (scale != m_scale) + m_scale = scale; + + XLOG("layer %d %x prepared at size (%d, %d) @ scale %.2f", m_layer->uniqueId(), + m_layer, w, h, scale); + + if (!m_tiledTexture) + m_tiledTexture = new TiledTexture(this); + + m_tiledTexture->prepare(state, m_pictureUsed != m_layer->pictureUsed()); +} + +bool PaintedSurface::draw() +{ + if (!m_layer || !m_layer->needsTexture()) + return false; + + bool askRedraw = false; + if (m_tiledTexture) + askRedraw = m_tiledTexture->draw(); + return askRedraw; +} + +bool PaintedSurface::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) +{ + if (!m_layer) + return false; + + m_layer->contentDraw(canvas); + m_pictureUsed = m_layer->pictureUsed(); + *pictureUsed = m_pictureUsed; + return true; +} + +void PaintedSurface::paintExtra(SkCanvas* canvas) +{ + if (m_layer) + m_layer->extraDraw(canvas); +} + +float PaintedSurface::opacity() { + if (m_layer) + return m_layer->drawOpacity(); + return 1.0; +} + +const TransformationMatrix* PaintedSurface::transform() { + if (!m_layer) + return 0; + + return m_layer->drawTransform(); +} + +void PaintedSurface::computeVisibleArea() { + if (!m_layer) + return; + IntRect layerRect = (*m_layer->drawTransform()).mapRect(m_area); + IntRect clippedRect = TilesManager::instance()->shader()->clippedRectWithViewport(layerRect); + m_visibleArea = (*m_layer->drawTransform()).inverse().mapRect(clippedRect); +} + +bool PaintedSurface::owns(BaseTileTexture* texture) +{ + if (m_tiledTexture) + return m_tiledTexture->owns(texture); + return false; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/PaintedSurface.h b/Source/WebCore/platform/graphics/android/PaintedSurface.h new file mode 100644 index 0000000..e95662d --- /dev/null +++ b/Source/WebCore/platform/graphics/android/PaintedSurface.h @@ -0,0 +1,103 @@ +/* + * 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 PaintedSurface_h +#define PaintedSurface_h + +#include "BaseTileTexture.h" +#include "ClassTracker.h" +#include "IntRect.h" +#include "LayerAndroid.h" +#include "TextureOwner.h" +#include "TiledTexture.h" +#include "TilesManager.h" +#include "TilePainter.h" +#include "TransformationMatrix.h" + +class SkCanvas; + +namespace WebCore { + +class PaintedSurface : public TilePainter { +public: + PaintedSurface(LayerAndroid* layer) + : m_layer(layer) + , m_tiledTexture(0) + , m_scale(0) + , m_pictureUsed(0) + { + TilesManager::instance()->addPaintedSurface(this); +#ifdef DEBUG_COUNT + ClassTracker::instance()->increment("PaintedSurface"); +#endif + } + virtual ~PaintedSurface() + { +#ifdef DEBUG_COUNT + ClassTracker::instance()->decrement("PaintedSurface"); +#endif + delete m_tiledTexture; + }; + + // PaintedSurface methods + + LayerAndroid* layer() { return m_layer; } + void prepare(GLWebViewState*); + bool draw(); + bool paint(SkCanvas*); + void removeLayer(LayerAndroid* layer); + void replaceLayer(LayerAndroid* layer); + + bool owns(BaseTileTexture* texture); + + void computeVisibleArea(); + + // TilePainter methods + virtual bool paint(BaseTile*, SkCanvas*, unsigned int*); + virtual void paintExtra(SkCanvas*); + virtual const TransformationMatrix* transform(); + + // used by TiledTexture + const IntRect& area() { return m_area; } + const IntRect& visibleArea() { return m_visibleArea; } + float scale() { return m_scale; } + float opacity(); + unsigned int pictureUsed() { return m_pictureUsed; } + TiledTexture* texture() { return m_tiledTexture; } + +private: + LayerAndroid* m_layer; + TiledTexture* m_tiledTexture; + + IntRect m_area; + IntRect m_visibleArea; + float m_scale; + + unsigned int m_pictureUsed; +}; + +} // namespace WebCore + +#endif // PaintedSurface_h diff --git a/Source/WebCore/platform/graphics/android/QueuedOperation.h b/Source/WebCore/platform/graphics/android/QueuedOperation.h index 98f3e2f..a2e49a7 100644 --- a/Source/WebCore/platform/graphics/android/QueuedOperation.h +++ b/Source/WebCore/platform/graphics/android/QueuedOperation.h @@ -31,7 +31,7 @@ namespace WebCore { class QueuedOperation { - public: +public: enum OperationType { Undefined, PaintTile, PaintLayer, DeleteTexture }; QueuedOperation(OperationType type, TiledPage* page) : m_type(type) @@ -42,19 +42,19 @@ class QueuedOperation { virtual int priority() { return -1; } OperationType type() const { return m_type; } TiledPage* page() const { return m_page; } - private: +private: OperationType m_type; TiledPage* m_page; }; class OperationFilter { - public: +public: virtual ~OperationFilter() {} virtual bool check(QueuedOperation* operation) = 0; }; class PageFilter : public OperationFilter { - public: +public: PageFilter(TiledPage* page) : m_page(page) {} virtual bool check(QueuedOperation* operation) { @@ -62,12 +62,12 @@ class PageFilter : public OperationFilter { return true; return false; } - private: +private: TiledPage* m_page; }; class PagePaintFilter : public OperationFilter { - public: +public: PagePaintFilter(TiledPage* page) : m_page(page) {} virtual bool check(QueuedOperation* operation) { @@ -76,7 +76,7 @@ class PagePaintFilter : public OperationFilter { return true; return false; } - private: +private: TiledPage* m_page; }; diff --git a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp index 35fc35a..4a18861 100644 --- a/Source/WebCore/platform/graphics/android/RasterRenderer.cpp +++ b/Source/WebCore/platform/graphics/android/RasterRenderer.cpp @@ -89,10 +89,13 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can bitmap.setConfig(SkBitmap::kARGB_8888_Config, renderInfo.invalRect->width(), renderInfo.invalRect->height()); bitmap.allocPixels(); - - // Clear the bitmap to whiteness first. - bitmap.setIsOpaque(true); - bitmap.eraseARGB(255, 255, 255, 255); + if (renderInfo.baseTile->isLayerTile()) { + bitmap.setIsOpaque(false); + bitmap.eraseARGB(0, 0, 0, 0); + } else { + bitmap.setIsOpaque(true); + bitmap.eraseARGB(255, 255, 255, 255); + } SkDevice* device = new SkDevice(NULL, bitmap, false); @@ -102,6 +105,7 @@ void RasterRenderer::setupCanvas(const TileRenderInfo& renderInfo, SkCanvas* can } canvas->setDevice(device); + device->unref(); // ensure the canvas origin is translated to the coordinates of our inval rect diff --git a/Source/WebCore/platform/graphics/android/ShaderProgram.h b/Source/WebCore/platform/graphics/android/ShaderProgram.h index c64a9b9..420c540 100644 --- a/Source/WebCore/platform/graphics/android/ShaderProgram.h +++ b/Source/WebCore/platform/graphics/android/ShaderProgram.h @@ -28,7 +28,7 @@ namespace WebCore { class ShaderProgram { - public: +public: ShaderProgram(); void init(); int projectionMatrix() { return m_hProjectionMatrix; } @@ -78,7 +78,7 @@ class ShaderProgram { void resetBlending(); - private: +private: GLuint loadShader(GLenum shaderType, const char* pSource); GLuint createProgram(const char* vertexSource, const char* fragmentSource); void setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle); diff --git a/Source/WebCore/platform/graphics/android/TextureOwner.h b/Source/WebCore/platform/graphics/android/TextureOwner.h index 15395bb..35d3389 100644 --- a/Source/WebCore/platform/graphics/android/TextureOwner.h +++ b/Source/WebCore/platform/graphics/android/TextureOwner.h @@ -26,6 +26,9 @@ #ifndef TextureOwner_h #define TextureOwner_h +class SkCanvas; +class Layer; + namespace WebCore { class TiledPage; @@ -38,6 +41,7 @@ public: virtual bool removeTexture(BaseTileTexture* texture) = 0; virtual TiledPage* page() = 0; virtual GLWebViewState* state() = 0; + virtual bool samePageAs(Layer* root) { return false; } }; } diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp index e6bef6a..704b7d0 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -30,7 +30,7 @@ #include "BaseLayerAndroid.h" #include "GLUtils.h" -#include "PaintLayerOperation.h" +#include "PaintTileOperation.h" #include "TilesManager.h" #ifdef DEBUG @@ -70,14 +70,9 @@ void TexturesGenerator::removePaintOperationsForPage(TiledPage* page, bool waitF removeOperationsForFilter(new PagePaintFilter(page), waitForRunning); } -void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer) +void TexturesGenerator::removeOperationsForPainter(TilePainter* painter, bool waitForRunning) { - removeOperationsForFilter(new PaintLayerBaseFilter(layer)); -} - -void TexturesGenerator::removeOperationsForTexture(LayerTexture* texture) -{ - removeOperationsForFilter(new PaintLayerTextureFilter(texture)); + removeOperationsForFilter(new TilePainterFilter(painter), waitForRunning); } void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) @@ -87,6 +82,9 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool waitForRunning) { + if (!filter) + return; + android::Mutex::Autolock lock(mRequestedOperationsLock); for (unsigned int i = 0; i < mRequestedOperations.size();) { QueuedOperation* operation = mRequestedOperations[i]; @@ -98,7 +96,7 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter, bool } } - if (waitForRunning) { + if (waitForRunning && m_currentOperation) { QueuedOperation* operation = m_currentOperation; if (operation && filter->check(operation)) m_waitForCompletion = true; @@ -168,6 +166,7 @@ bool TexturesGenerator::threadLoop() bool stop = false; while (!stop) { mRequestedOperationsLock.lock(); + XLOG("threadLoop, %d operations in the queue", mRequestedOperations.size()); if (mRequestedOperations.size()) m_currentOperation = popNext(); mRequestedOperationsLock.unlock(); diff --git a/Source/WebCore/platform/graphics/android/TexturesGenerator.h b/Source/WebCore/platform/graphics/android/TexturesGenerator.h index b03f52d..bac198c 100644 --- a/Source/WebCore/platform/graphics/android/TexturesGenerator.h +++ b/Source/WebCore/platform/graphics/android/TexturesGenerator.h @@ -28,9 +28,9 @@ #if USE(ACCELERATED_COMPOSITING) -#include "LayerTexture.h" #include "QueuedOperation.h" #include "TiledPage.h" +#include "TilePainter.h" #include <utils/threads.h> namespace WebCore { @@ -49,8 +49,7 @@ public: virtual status_t readyToRun(); void removeOperationsForPage(TiledPage* page); - void removeOperationsForBaseLayer(BaseLayerAndroid* layer); - void removeOperationsForTexture(LayerTexture* texture); + void removeOperationsForPainter(TilePainter* painter, bool waitForRunning); void removePaintOperationsForPage(TiledPage* page, bool waitForRunning); void removeOperationsForFilter(OperationFilter* filter); void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning); diff --git a/Source/WebCore/platform/graphics/android/PaintLayerOperation.h b/Source/WebCore/platform/graphics/android/TilePainter.h index e688d87..191edf3 100644 --- a/Source/WebCore/platform/graphics/android/PaintLayerOperation.h +++ b/Source/WebCore/platform/graphics/android/TilePainter.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, The Android Open Source Project + * 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 @@ -23,52 +23,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PaintLayerOperation_h -#define PaintLayerOperation_h +#ifndef TilePainter_h +#define TilePainter_h -#include "QueuedOperation.h" +#include "TransformationMatrix.h" -class Layer; +class SkCanvas; namespace WebCore { -class LayerAndroid; -class LayerTexture; +class BaseTile; -class PaintLayerOperation : public QueuedOperation { - public: - PaintLayerOperation(LayerAndroid* layer) - : QueuedOperation(QueuedOperation::PaintLayer, 0) - , m_layer(layer) {} - virtual ~PaintLayerOperation() {} - virtual bool operator==(const QueuedOperation* operation); - virtual void run(); - Layer* baseLayer(); - LayerAndroid* layer() { return m_layer; } - LayerTexture* texture(); - - private: - LayerAndroid* m_layer; -}; - -class PaintLayerBaseFilter : public OperationFilter { - public: - PaintLayerBaseFilter(Layer* layer) : m_baseLayer(layer) {} - virtual bool check(QueuedOperation* operation); - - private: - Layer* m_baseLayer; -}; - -class PaintLayerTextureFilter : public OperationFilter { - public: - PaintLayerTextureFilter(LayerTexture* texture) : m_texture(texture) {} - virtual bool check(QueuedOperation* operation); - - private: - LayerTexture* m_texture; +class TilePainter { +public: + virtual ~TilePainter() { } + virtual bool paint(BaseTile* tile, SkCanvas*, unsigned int*) = 0; + virtual void paintExtra(SkCanvas*) = 0; + virtual const TransformationMatrix* transform() { return 0; } }; } -#endif // PaintLayerOperation_h +#endif // TilePainter_h diff --git a/Source/WebCore/platform/graphics/android/TiledPage.cpp b/Source/WebCore/platform/graphics/android/TiledPage.cpp index 1306a1d..477ae7c 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.cpp +++ b/Source/WebCore/platform/graphics/android/TiledPage.cpp @@ -166,12 +166,12 @@ void TiledPage::prepareRow(bool goingLeft, int tilesInRow, int firstTileX, int y if (!currentTile && availableTile) { currentTile = availableTile; - currentTile->setContents(this, x, y); } if (currentTile) { - currentTile->setScale(m_scale); currentTile->setGLWebViewState(m_glWebViewState); + currentTile->setContents(this, x, y, m_scale); + currentTile->setPage(this); // ensure there is a texture associated with the tile and then check to // see if the texture is dirty and in need of repainting @@ -341,11 +341,17 @@ void TiledPage::draw(float transparency, const SkIRect& tileBounds) } } -unsigned int TiledPage::paintBaseLayerContent(SkCanvas* canvas) +bool TiledPage::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) +{ + if (!m_glWebViewState) + return false; + + *pictureUsed = m_glWebViewState->paintBaseLayerContent(canvas); + return true; +} + +void TiledPage::paintExtra(SkCanvas* canvas) { - if (m_glWebViewState) - return m_glWebViewState->paintBaseLayerContent(canvas); - return 0; } TiledPage* TiledPage::sibling() diff --git a/Source/WebCore/platform/graphics/android/TiledPage.h b/Source/WebCore/platform/graphics/android/TiledPage.h index 1aa3e61..078ce48 100644 --- a/Source/WebCore/platform/graphics/android/TiledPage.h +++ b/Source/WebCore/platform/graphics/android/TiledPage.h @@ -32,6 +32,8 @@ #include "SkCanvas.h" #include "SkRegion.h" +#include "TilePainter.h" + namespace WebCore { class GLWebViewState; @@ -47,7 +49,7 @@ class IntRect; * background TilePage at the new scale factor. When the background TilePage is * ready, we swap it with the currently displaying TiledPage. */ -class TiledPage { +class TiledPage : public TilePainter { public: TiledPage(int id, GLWebViewState* state); ~TiledPage(); @@ -62,8 +64,11 @@ public: // draw the page on the screen void draw(float transparency, const SkIRect& tileBounds); + // TilePainter implementation // used by individual tiles to generate the bitmap for their tile - unsigned int paintBaseLayerContent(SkCanvas*); + bool paint(BaseTile*, SkCanvas*, unsigned int*); + void paintExtra(SkCanvas*); + // used by individual tiles to get the information about the current picture GLWebViewState* glWebViewState() { return m_glWebViewState; } diff --git a/Source/WebCore/platform/graphics/android/TiledTexture.cpp b/Source/WebCore/platform/graphics/android/TiledTexture.cpp new file mode 100644 index 0000000..3dc0956 --- /dev/null +++ b/Source/WebCore/platform/graphics/android/TiledTexture.cpp @@ -0,0 +1,231 @@ +/* + * 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 "TiledTexture.h" + +#include "TilesManager.h" +#include "TilesTracker.h" + +#include "PaintedSurface.h" +#include "PaintTileOperation.h" +#include "SkCanvas.h" + +#ifdef DEBUG + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__) + +#else + +#undef XLOG +#define XLOG(...) + +#endif // DEBUG + +namespace WebCore { + +void TiledTexture::prepare(GLWebViewState* state, bool repaint) +{ + if (!m_surface) + return; + + // first, how many tiles do we need + IntRect visibleArea = m_surface->visibleArea(); + IntRect area(visibleArea.x() * m_surface->scale(), + visibleArea.y() * m_surface->scale(), + visibleArea.width() * m_surface->scale(), + visibleArea.height() * m_surface->scale()); + + for (unsigned int i = 0; i < m_tiles.size(); i++) { + BaseTile* tile = m_tiles[i]; + tile->setUsedLevel(-1); + } + + if (area.width() == 0 && area.height() == 0) { + m_area.setWidth(0); + m_area.setHeight(0); + return; + } + + int tileWidth = TilesManager::instance()->layerTileWidth(); + int tileHeight = TilesManager::instance()->layerTileHeight(); + + m_area.setX(area.x() / tileWidth); + m_area.setY(area.y() / tileHeight); + 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); + + bool goingDown = m_prevTileY < m_area.y(); + m_prevTileY = m_area.y(); + + if (m_surface->scale() != m_prevScale) + TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(m_surface->scale())); + + m_prevScale = m_surface->scale(); + + for (int i = 0; i < m_area.width(); i++) { + if (goingDown) { + for (int j = 0; j < m_area.height(); j++) { + prepareTile(repaint, m_area.x() + i, m_area.y() + j); + } + } else { + for (int j = m_area.height() - 1; j >= 0; j--) { + prepareTile(repaint, m_area.x() + i, m_area.y() + j); + } + } + } +} + +void TiledTexture::prepareTile(bool repaint, int x, int y) +{ + BaseTile* tile = getTile(x, y); + if (!tile) { + tile = new BaseTile(true); + m_tiles.append(tile); + } + tile->reserveTexture(); + if (!tile->texture()) + return; + + tile->setContents(this, x, y, m_surface->scale()); + tile->setUsedLevel(0); + + bool schedule = false; + if (repaint) + tile->fullInval(); + if (!tile->isTileReady()) + schedule = true; + if (repaint || tile->isDirty()) + schedule = true; + + if (schedule && !tile->isRepaintPending()) { + PaintTileOperation *operation = new PaintTileOperation(tile); + TilesManager::instance()->scheduleOperation(operation); + } +} + +BaseTile* TiledTexture::getTile(int x, int y) +{ + for (unsigned int i = 0; i <m_tiles.size(); i++) { + BaseTile* tile = m_tiles[i]; + if (tile->x() == x && tile->y() == y) + return tile; + } + return 0; +} + +bool TiledTexture::draw() +{ +#ifdef DEBUG + TilesManager::instance()->getTilesTracker()->trackLayer(); +#endif + + bool askRedraw = false; + if (m_area.width() == 0 || m_area.height() == 0) + return askRedraw; + +#ifdef DEBUG + TilesManager::instance()->getTilesTracker()->trackVisibleLayer(); +#endif + + float m_invScale = 1 / m_surface->scale(); + const float tileWidth = TilesManager::layerTileWidth() * m_invScale; + const float tileHeight = TilesManager::layerTileHeight() * m_invScale; + XLOG("draw tile %x, tiles %d", this, m_tiles.size()); + for (unsigned int i = 0; i <m_tiles.size(); i++) { + BaseTile* tile = m_tiles[i]; + if (tile->x() >= m_area.x() + && tile->x() < m_area.x() + m_area.width() + && tile->y() >= m_area.y() + && tile->y() < m_area.y() + m_area.height()) { + SkRect rect; + rect.fLeft = tile->x() * tileWidth; + rect.fTop = tile->y() * tileHeight; + rect.fRight = rect.fLeft + tileWidth; + rect.fBottom = rect.fTop + tileHeight; + XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f [ready: %d]", i, this, tile->painter(), tile, tile->x(), tile->y(), tile->scale(), tile->isTileReady()); + askRedraw |= !tile->isTileReady(); + tile->draw(m_surface->opacity(), rect, m_surface->scale()); +#ifdef DEBUG + TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->texture()); +#endif + } + } + return askRedraw; +} + +bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed) +{ + if (!m_surface) + return false; + + XLOG("painting scheduled tile(%x : %d, %d, %.2f, %x) for %x", + tile, tile->x(), tile->y(), tile->scale(), tile->painter(), this); + return m_surface->paint(tile, canvas, pictureUsed); +} + +void TiledTexture::paintExtra(SkCanvas* canvas) +{ + m_surface->paintExtra(canvas); +} + +const TransformationMatrix* TiledTexture::transform() +{ + return m_surface->transform(); +} + +void TiledTexture::removeTiles() +{ + TilesManager::instance()->removeOperationsForPainter(this, true); + for (unsigned int i = 0; i < m_tiles.size(); i++) { + delete m_tiles[i]; + } +} + +bool TiledTexture::owns(BaseTileTexture* texture) +{ + for (unsigned int i = 0; i < m_tiles.size(); i++) { + BaseTile* tile = m_tiles[i]; + if (tile->texture() == texture) + return true; + } + return false; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/LayerTexture.h b/Source/WebCore/platform/graphics/android/TiledTexture.h index 7a6c369..b6d5b4c 100644 --- a/Source/WebCore/platform/graphics/android/LayerTexture.h +++ b/Source/WebCore/platform/graphics/android/TiledTexture.h @@ -1,5 +1,5 @@ /* - * Copyright 2010, The Android Open Source Project + * 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 @@ -23,53 +23,69 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef LayerTexture_h -#define LayerTexture_h +#ifndef TiledTexture_h +#define TiledTexture_h #include "BaseTileTexture.h" #include "ClassTracker.h" #include "IntRect.h" +#include "LayerAndroid.h" +#include "TextureOwner.h" +#include "BaseTile.h" +#include "TilePainter.h" + +class SkCanvas; namespace WebCore { -class LayerTexture : public BaseTileTexture { - public: - LayerTexture(uint32_t w, uint32_t h) - : BaseTileTexture(w, h) - , m_layerId(0) - , m_scale(1) - , m_ready(false) +class PaintedSurface; + +class TiledTexture : public TilePainter { +public: + TiledTexture(PaintedSurface* surface) + : m_surface(surface) + , m_prevTileX(0) + , m_prevTileY(0) + , m_prevScale(1) { #ifdef DEBUG_COUNT - ClassTracker::instance()->increment("LayerTexture"); + ClassTracker::instance()->increment("TiledTexture"); #endif } - virtual ~LayerTexture() + virtual ~TiledTexture() { #ifdef DEBUG_COUNT - ClassTracker::instance()->decrement("LayerTexture"); + ClassTracker::instance()->decrement("TiledTexture"); #endif + removeTiles(); }; - void setTextureInfoFor(LayerAndroid* layer); - bool readyFor(LayerAndroid* layer); - void setRect(const IntRect& r) { m_rect = r; } - IntRect& rect() { return m_rect; } - int id() { return m_layerId; } - float scale() { return m_scale; } - void setId(int id) { m_layerId = id; } - void setScale(float scale) { m_scale = scale; } - bool ready() { return m_ready; } - unsigned int pictureUsed(); - - private: - - IntRect m_rect; - int m_layerId; - float m_scale; - bool m_ready; + void prepare(GLWebViewState* state, bool repaint); + bool draw(); + + void prepareTile(bool repaint, int x, int y); + + BaseTile* getTile(int x, int y); + + void removeTiles(); + bool owns(BaseTileTexture* texture); + + // TilePainter methods + bool paint(BaseTile* tile, SkCanvas*, unsigned int*); + virtual void paintExtra(SkCanvas*); + virtual const TransformationMatrix* transform(); + +private: + PaintedSurface* m_surface; + Vector<BaseTile*> m_tiles; + + IntRect m_area; + + int m_prevTileX; + int m_prevTileY; + float m_prevScale; }; } // namespace WebCore -#endif // LayerTexture_h +#endif // TiledTexture_h diff --git a/Source/WebCore/platform/graphics/android/TilesManager.cpp b/Source/WebCore/platform/graphics/android/TilesManager.cpp index ad4cbd3..3297cc2 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.cpp +++ b/Source/WebCore/platform/graphics/android/TilesManager.cpp @@ -29,17 +29,22 @@ #if USE(ACCELERATED_COMPOSITING) #include "BaseTile.h" +#include "PaintedSurface.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkPaint.h" #include <cutils/atomic.h> -#ifdef DEBUG #include <cutils/log.h> #include <wtf/CurrentTime.h> #include <wtf/text/CString.h> +#undef XLOGC +#define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) + +#ifdef DEBUG + #undef XLOG #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesManager", __VA_ARGS__) @@ -65,6 +70,9 @@ #define MAX_TEXTURE_ALLOCATION 3+(6+EXPANDED_TILE_BOUNDS_X*2)*(4+EXPANDED_TILE_BOUNDS_Y*2)*2 #define TILE_WIDTH 300 #define TILE_HEIGHT 300 +#define LAYER_TILE_WIDTH 256 +#define LAYER_TILE_HEIGHT 256 +#define LAYER_TILES 10 // Define a maximum amount of ram used by layers #define MAX_LAYERS_ALLOCATION 33554432 // 32Mb @@ -117,6 +125,17 @@ void TilesManager::allocateTiles() m_textures.append(loadedTexture); nbTexturesAllocated++; } + + for (int i = 0; i < LAYER_TILES; i++) { + BaseTileTexture* texture = new BaseTileTexture( + layerTileWidth(), layerTileHeight()); + // the atomic load ensures that the texture has been fully initialized + // before we pass a pointer for other threads to operate on + BaseTileTexture* loadedTexture = + reinterpret_cast<BaseTileTexture*>( + android_atomic_acquire_load(reinterpret_cast<int32_t*>(&texture))); + m_tilesTextures.append(loadedTexture); + } XLOG("allocated %d textures", nbTexturesAllocated); } @@ -156,6 +175,50 @@ void TilesManager::resetTextureUsage(TiledPage* page) } } +void TilesManager::swapLayersTextures(LayerAndroid* oldTree, LayerAndroid* newTree) +{ + if (newTree) + newTree->assignTexture(oldTree); +} + +void TilesManager::addPaintedSurface(PaintedSurface* surface) +{ + m_paintedSurfaces.append(surface); +} + +void TilesManager::cleanupTilesTextures() +{ + // release existing surfaces without layers + Vector<PaintedSurface*> collect; + for (unsigned int i = 0; i < m_paintedSurfaces.size(); i++) { + PaintedSurface* surface = m_paintedSurfaces[i]; + if (!surface->layer()) + collect.append(surface); + } + XLOG("remove %d / %d PaintedSurfaces", collect.size(), m_paintedSurfaces.size()); + for (unsigned int i = 0; i < collect.size(); i++) { + m_paintedSurfaces.remove(m_paintedSurfaces.find(collect[i])); + TilePainter* painter = collect[i]->texture(); + m_pixmapsGenerationThread->removeOperationsForPainter(painter, true); + XLOG("destroy %x (%x)", collect[i], painter); + delete collect[i]; + } + for (unsigned int i = 0; i < m_tilesTextures.size(); i++) { + BaseTileTexture* texture = m_tilesTextures[i]; + texture->setUsedLevel(-1); + if (texture->owner()) { + bool keep = false; + for (unsigned int j = 0; j < m_paintedSurfaces.size(); j++) { + if (m_paintedSurfaces[j]->owns(texture)) + keep = true; + } + if (!keep) { + texture->release(texture->owner()); + } + } + } +} + BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) { android::Mutex::Autolock lock(m_texturesLock); @@ -168,6 +231,23 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) return owner->texture(); } + if (owner->isLayerTile()) { + unsigned int max = m_tilesTextures.size(); + for (unsigned int i = 0; i < max; i++) { + BaseTileTexture* texture = m_tilesTextures[i]; + if (!texture->owner() && texture->acquire(owner)) { + return texture; + } + if (texture->usedLevel() != 0 && texture->acquire(owner)) { + return texture; + } + if (texture->scale() != owner->scale() && texture->acquire(owner)) { + return texture; + } + } + return 0; + } + // The heuristic for selecting a texture is as follows: // 1. If usedLevel == -1, break with that one // 2. Otherwise, select the highest usedLevel available @@ -212,160 +292,6 @@ BaseTileTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } -LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer, - const IntRect& rect, - bool any, - LayerTexture* texture) -{ - android::Mutex::Autolock lock(m_texturesLock); - LayerTexture* best = 0; - unsigned newestPictureUsed = 0; - for (unsigned int i = 0; i< m_layersTextures.size(); i++) { - if (m_layersTextures[i]->id() != layer->uniqueId()) - continue; - if (!any && rect != m_layersTextures[i]->rect()) - continue; - if (!any && layer->getScale() != m_layersTextures[i]->scale()) - continue; - if (any && texture == m_layersTextures[i]) - continue; - - if (m_layersTextures[i]->ready()) { - unsigned int pictureUsed = m_layersTextures[i]->pictureUsed(); - if (pictureUsed >= newestPictureUsed) { - newestPictureUsed = pictureUsed; - best = m_layersTextures[i]; - } - } - - XLOG("return layer %d (%x) for tile %d (%x)", - i, m_layersTextures[i], - layer->uniqueId(), layer); - } - - if (best && best->acquire(layer, any)) - return best; - return 0; -} - -void TilesManager::printLayersTextures(const char* s) -{ -#ifdef DEBUG - XLOG(">>> print layers textures (%s)", s); - for (unsigned int i = 0; i< m_layersTextures.size(); i++) { - XLOG("[%d] %s, texture %x for layer %d (w: %.2f, h: %.2f), owner: %x", - i, s, m_layersTextures[i], - m_layersTextures[i]->id(), - m_layersTextures[i]->getSize().fWidth, - m_layersTextures[i]->getSize().fHeight, - m_layersTextures[i]->owner()); - } - XLOG("<<< print layers textures (%s)", s); -#endif -} - -void TilesManager::cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup) -{ - android::Mutex::Autolock lock(m_texturesLock); - Layer* rootLayer = 0; - if (layer) - rootLayer = layer->getRootLayer(); -#ifdef DEBUG - if (forceCleanup) - XLOG("FORCE cleanup"); - XLOG("before cleanup, memory %d", m_layersMemoryUsage); - printLayersTextures("before cleanup"); -#endif - for (unsigned int i = 0; i< m_layersTextures.size();) { - LayerTexture* texture = m_layersTextures[i]; - - if (forceCleanup && texture->owner()) { - LayerAndroid* textureLayer = - static_cast<LayerAndroid*>(texture->owner()); - if (textureLayer->getRootLayer() != rootLayer) { - // We only want to force destroy layers - // that are not used by the current page - XLOG("force removing texture %x for layer %d", - texture, textureLayer->uniqueId()); - textureLayer->removeTexture(texture); - } - } - - // We only try to destroy textures that have no owners. - // This could be due to: - // 1) - the LayerAndroid dtor has been called (i.e. when swapping - // a LayerAndroid tree with a new one) - // 2) - or due to the above code, forcing a destroy. - // If the texture has been forced to be released (case #2), it - // could still be in use (in the middle of being painted). So we - // need to check that's not the case by checking busy(). See - // LayerAndroid::paintBitmapGL(). - if (!texture->owner() && !texture->busy()) { - m_layersMemoryUsage -= (int) texture->getSize().fWidth - * (int) texture->getSize().fHeight * BYTES_PER_PIXEL; - m_layersTextures.remove(i); - // We can destroy the texture. We first remove it from the textures - // list, and then remove any queued drawing. At this point we know - // the texture has been removed from the layer, and that it's not - // busy, so it's safe to delete. - m_pixmapsGenerationThread->removeOperationsForTexture(texture); - XLOG("delete texture %x", texture); - delete texture; - } else { - // only iterate if we don't delete (if we delete, no need to as we - // remove the element from the array) - i++; - } - } -#ifdef DEBUG - printLayersTextures("after cleanup"); - XLOG("after cleanup, memory %d", m_layersMemoryUsage); -#endif -} - -LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const IntRect& rect) -{ - int w = rect.width() * layer->getScale(); - int h = rect.height() * layer->getScale(); - unsigned int size = w * h * BYTES_PER_PIXEL; - - // We will not allocate textures that: - // 1) cannot be handled by the graphic card (maxTextureSize & - // totalMaxTextureSize) - // 2) will make us go past our texture limit (MAX_LAYERS_ALLOCATION) - - GLint maxTextureSize = getMaxTextureSize(); - unsigned totalMaxTextureSize = maxTextureSize * maxTextureSize * BYTES_PER_PIXEL; - bool large = w > maxTextureSize || h > maxTextureSize || size > totalMaxTextureSize; - XLOG("createTextureForLayer(%d) @scale %.2f => %d, %d (too large? %x)", layer->uniqueId(), - layer->getScale(), w, h, large); - - // For now just return 0 if too large - if (large) - return 0; - - if (w == 0 || h == 0) // empty layer - return 0; - - 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); - texture->setScale(layer->getScale()); - - android::Mutex::Autolock lock(m_texturesLock); - m_layersTextures.append(texture); - texture->acquire(layer); - m_layersMemoryUsage += size; - return texture; -} - int TilesManager::maxLayersAllocation() { return MAX_LAYERS_ALLOCATION; @@ -411,6 +337,16 @@ float TilesManager::tileHeight() return TILE_HEIGHT; } +float TilesManager::layerTileWidth() +{ + return LAYER_TILE_WIDTH; +} + +float TilesManager::layerTileHeight() +{ + return LAYER_TILE_HEIGHT; +} + int TilesManager::expandedTileBoundsX() { return m_expandedTileBounds ? EXPANDED_TILE_BOUNDS_X : 0; } diff --git a/Source/WebCore/platform/graphics/android/TilesManager.h b/Source/WebCore/platform/graphics/android/TilesManager.h index 0a2fb798..25e487d 100644 --- a/Source/WebCore/platform/graphics/android/TilesManager.h +++ b/Source/WebCore/platform/graphics/android/TilesManager.h @@ -31,17 +31,19 @@ #include "BaseTile.h" #include "BaseTileTexture.h" #include "LayerAndroid.h" -#include "LayerTexture.h" #include "ShaderProgram.h" #include "TexturesGenerator.h" #include "TiledPage.h" #include "TilesProfiler.h" +#include "TilesTracker.h" #include "VideoLayerManager.h" #include <utils/threads.h> #include <wtf/HashMap.h> namespace WebCore { +class PaintedSurface; + class TilesManager { public: static TilesManager* instance(); @@ -53,24 +55,24 @@ public: return gInstance != 0; } - void removeOperationsForPage(TiledPage* page) + void removeOperationsForFilter(OperationFilter* filter, bool waitForRunning = false) { - m_pixmapsGenerationThread->removeOperationsForPage(page); + m_pixmapsGenerationThread->removeOperationsForFilter(filter, waitForRunning); } - void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) + void removeOperationsForPage(TiledPage* page) { - m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); + m_pixmapsGenerationThread->removeOperationsForPage(page); } - void removeOperationsForBaseLayer(BaseLayerAndroid* layer) + void removeOperationsForPainter(TilePainter* painter, bool waitForCompletion) { - m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer); + m_pixmapsGenerationThread->removeOperationsForPainter(painter, waitForCompletion); } - void removeOperationsForTexture(LayerTexture* texture) + void removePaintOperationsForPage(TiledPage* page, bool waitForCompletion) { - m_pixmapsGenerationThread->removeOperationsForTexture(texture); + m_pixmapsGenerationThread->removePaintOperationsForPage(page, waitForCompletion); } void scheduleOperation(QueuedOperation* operation) @@ -78,16 +80,15 @@ public: m_pixmapsGenerationThread->scheduleOperation(operation); } + void swapLayersTextures(LayerAndroid* newTree, LayerAndroid* oldTree); + void addPaintedSurface(PaintedSurface* surface); + ShaderProgram* shader() { return &m_shader; } VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; } BaseTileTexture* getAvailableTexture(BaseTile* owner); - void printLayersTextures(const char* s); - void cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup = false); - LayerTexture* getExistingTextureForLayer(LayerAndroid* layer, const IntRect& rect, - bool any = false, LayerTexture* texture = 0); - LayerTexture* createTextureForLayer(LayerAndroid* layer, const IntRect& rect); + void cleanupTilesTextures(); void markGeneratorAsReady() { @@ -108,6 +109,8 @@ public: void setMaxTextureCount(int max); static float tileWidth(); static float tileHeight(); + static float layerTileWidth(); + static float layerTileHeight(); int expandedTileBoundsX(); int expandedTileBoundsY(); void registerGLWebViewState(GLWebViewState* state); @@ -132,7 +135,11 @@ public: } TilesProfiler* getProfiler() { - return &profiler; + return &m_profiler; + } + + TilesTracker* getTilesTracker() { + return &m_tilesTracker; } private: @@ -147,7 +154,8 @@ private: } Vector<BaseTileTexture*> m_textures; - Vector<LayerTexture*> m_layersTextures; + Vector<BaseTileTexture*> m_tilesTextures; + Vector<PaintedSurface*> m_paintedSurfaces; unsigned int m_layersMemoryUsage; @@ -174,7 +182,8 @@ private: unsigned int getGLWebViewStateDrawCount(GLWebViewState* state); - TilesProfiler profiler; + TilesProfiler m_profiler; + TilesTracker m_tilesTracker; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/android/LayerTexture.cpp b/Source/WebCore/platform/graphics/android/TilesTracker.h index f311f32..202d072 100644 --- a/Source/WebCore/platform/graphics/android/LayerTexture.cpp +++ b/Source/WebCore/platform/graphics/android/TilesTracker.h @@ -23,49 +23,63 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "LayerTexture.h" +#ifndef TilesTracker_h +#define TilesTracker_h -#include "LayerAndroid.h" +#if USE(ACCELERATED_COMPOSITING) + +#include <cutils/log.h> +#include <wtf/CurrentTime.h> +#include <wtf/text/CString.h> + +#undef XLOG +#define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TilesTracker", __VA_ARGS__) namespace WebCore { -unsigned int LayerTexture::pictureUsed() -{ - consumerLock(); - TextureTileInfo* info = m_texturesInfo.get(getReadableTexture()); - unsigned int pictureUsed = 0; - if (info) - pictureUsed = info->m_picture; - consumerRelease(); - return pictureUsed; -} +class TilesTracker { +public: + TilesTracker() { + clear(); + } + + void track(bool ready, bool haveTexture) { + m_nbTextures++; + if (ready) + m_nbTexturesReady++; + else + m_nbTexturesNotReady++; + if (haveTexture) + m_nbTexturesUsed++; + } -void LayerTexture::setTextureInfoFor(LayerAndroid* layer) -{ - TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture()); - if (!textureInfo) { - textureInfo = new TextureTileInfo(); - } - textureInfo->m_layerId = layer->uniqueId(); - textureInfo->m_picture = layer->pictureUsed(); - textureInfo->m_scale = layer->getScale(); - m_texturesInfo.set(getWriteableTexture(), textureInfo); - m_layerId = layer->uniqueId(); - m_scale = layer->getScale(); - if (!m_ready) - m_ready = true; -} + void clear() { + m_nbLayers = 0; + m_nbVisibleLayers = 0; + m_nbTextures = 0; + m_nbTexturesReady = 0; + m_nbTexturesNotReady = 0; + m_nbTexturesUsed = 0; + } -bool LayerTexture::readyFor(LayerAndroid* layer) -{ - TextureTileInfo* info = m_texturesInfo.get(getReadableTexture()); - if (info && - info->m_layerId == layer->uniqueId() && - info->m_scale == layer->getScale() && - info->m_picture == layer->pictureUsed()) - return true; - return false; -} + void trackLayer() { m_nbLayers++; } + void trackVisibleLayer() { m_nbVisibleLayers++; } + + void showTrackTextures() { + XLOG("We had %d/%d layers needing %d textures, we had %d, %d were ready, %d were not", + m_nbLayers, m_nbVisibleLayers, m_nbTextures, m_nbTexturesUsed, m_nbTexturesReady, m_nbTexturesNotReady); + } + +private: + int m_nbLayers; + int m_nbVisibleLayers; + int m_nbTextures; + int m_nbTexturesReady; + int m_nbTexturesNotReady; + int m_nbTexturesUsed; +}; } // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) +#endif // TilesTracker_h diff --git a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp index 0f34c97..9576ed1 100644 --- a/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/VideoLayerAndroid.cpp @@ -166,12 +166,12 @@ bool VideoLayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) // on the player's state. if (m_playerState == PREPARING) { // Show the progressing animation, with two rotating circles - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect, + TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true); TransformationMatrix addReverseRotation; - TransformationMatrix addRotation = drawTransform(); + TransformationMatrix addRotation = m_drawTransform; addRotation.translate(innerRect.fLeft, innerRect.fTop); addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2); addReverseRotation = addRotation; @@ -198,7 +198,7 @@ bool VideoLayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) m_surfaceTexture->getTransformMatrix(surfaceMatrix); GLuint textureId = TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); - TilesManager::instance()->shader()->drawVideoLayerQuad(drawTransform(), + TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, surfaceMatrix, rect, textureId); TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(), @@ -210,15 +210,15 @@ bool VideoLayerAndroid::drawGL(GLWebViewState* glWebViewState, SkMatrix& matrix) TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId()); if (textureId && matrix) { // Show the screen shot for each video. - TilesManager::instance()->shader()->drawVideoLayerQuad(drawTransform(), + TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, matrix, rect, textureId); } else { // Show the static poster b/c there is no screen shot available. - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect, + TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, m_backgroundTextureId, 1, true); - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), innerRect, + TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect, m_posterTextureId, 1, true); } |