diff options
author | Nicolas Roard <nicolas@android.com> | 2011-01-18 13:36:31 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-01-18 13:36:31 -0800 |
commit | 3eee7f647df0557a7c476e21afb08031736aac8c (patch) | |
tree | 03b6dae6f36cd687dadebebf93a835a97ba0c38c /WebCore/platform | |
parent | bca79c07f17d228a8cb759491451476b79a0a212 (diff) | |
parent | fed0f3819356e8f1bdb6fd97c0265e2bfff1dacb (diff) | |
download | external_webkit-3eee7f647df0557a7c476e21afb08031736aac8c.zip external_webkit-3eee7f647df0557a7c476e21afb08031736aac8c.tar.gz external_webkit-3eee7f647df0557a7c476e21afb08031736aac8c.tar.bz2 |
Merge "Implement partial layer rendering (support for large layers) Also fix a couple of potential ANRs" into honeycomb
Diffstat (limited to 'WebCore/platform')
12 files changed, 114 insertions, 45 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp index ddfa9a0..3462975 100644 --- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp +++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp @@ -138,7 +138,7 @@ bool BackedDoubleBufferedTexture::setOwner(TextureOwner* owner) android::Mutex::Autolock lock(m_busyLock); if (!m_busy) { if (m_owner) - m_owner->removeTexture(); + m_owner->removeTexture(this); m_owner = owner; return true; } diff --git a/WebCore/platform/graphics/android/BaseTile.cpp b/WebCore/platform/graphics/android/BaseTile.cpp index a506ac9..35de698 100644 --- a/WebCore/platform/graphics/android/BaseTile.cpp +++ b/WebCore/platform/graphics/android/BaseTile.cpp @@ -115,12 +115,13 @@ void BaseTile::reserveTexture() m_texture = texture; } -void BaseTile::removeTexture() +void BaseTile::removeTexture(BackedDoubleBufferedTexture* texture) { XLOG("%x removeTexture res: %x...", this, m_texture); // We update atomically, so paintBitmap() can see the correct value android::AutoMutex lock(m_atomicSync); - m_texture = 0; + if (m_texture == texture) + m_texture = 0; } void BaseTile::setScale(float scale) diff --git a/WebCore/platform/graphics/android/BaseTile.h b/WebCore/platform/graphics/android/BaseTile.h index f6ffe38..a7eae23 100644 --- a/WebCore/platform/graphics/android/BaseTile.h +++ b/WebCore/platform/graphics/android/BaseTile.h @@ -90,7 +90,7 @@ public: BackedDoubleBufferedTexture* texture() { return m_texture; } // TextureOwner implementation - virtual void removeTexture(); + virtual void removeTexture(BackedDoubleBufferedTexture* texture); virtual TiledPage* page() { return m_page; } private: diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp index 64060f7..95d4ff4 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.cpp +++ b/WebCore/platform/graphics/android/LayerAndroid.cpp @@ -152,22 +152,33 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(), gDebugLayerAndroidInstances++; } -void LayerAndroid::removeTexture() +void LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture) { - XLOG("remove texture (m_drawingTexture: %x, m_reservedTexture: %x)", - m_drawingTexture, m_reservedTexture); + LayerTexture* texture = static_cast<LayerTexture*>(aTexture); android::AutoMutex lock(m_atomicSync); - if (m_drawingTexture) - m_drawingTexture->release(this); - if (m_reservedTexture && m_reservedTexture != m_drawingTexture) - m_reservedTexture->release(this); - m_drawingTexture = 0; - m_reservedTexture = 0; + if (!texture) { // remove ourself from both textures + if (m_drawingTexture) + m_drawingTexture->release(this); + if (m_reservedTexture && + m_reservedTexture != m_drawingTexture) + m_reservedTexture->release(this); + } else { + if (m_drawingTexture && m_drawingTexture == texture) + m_drawingTexture->release(this); + if (m_reservedTexture && + m_reservedTexture == texture && + m_reservedTexture != m_drawingTexture) + m_reservedTexture->release(this); + } + if (m_drawingTexture && m_drawingTexture->owner() != this) + m_drawingTexture = 0; + if (m_reservedTexture && m_reservedTexture->owner() != this) + m_reservedTexture = 0; } LayerAndroid::~LayerAndroid() { - removeTexture(); + removeTexture(0); removeChildren(); m_contentsImage->safeUnref(); m_recordingPicture->safeUnref(); @@ -539,6 +550,7 @@ void LayerAndroid::updateGLPositions(const TransformationMatrix& parentMatrix, localMatrix.setM34(0); localMatrix.setM43(0); } + // now apply it to our children if (!m_childrenTransform.isIdentity()) { @@ -568,13 +580,29 @@ void LayerAndroid::reserveGLTextures() this->getChild(i)->reserveGLTextures(); LayerTexture* reservedTexture = 0; - if (needsTexture()) - reservedTexture = TilesManager::instance()->getExistingTextureForLayer(this); + if (needsTexture()) { + // Compute the layer size & position we need (clipped to the viewport) + IntRect r(0, 0, getWidth(), getHeight()); + IntRect tr = drawTransform().mapRect(r); + IntRect cr = TilesManager::instance()->shader()->clippedRectWithViewport(tr); + m_layerTextureRect = drawTransform().inverse().mapRect(cr); + + 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) + m_drawingTexture = TilesManager::instance()->getExistingTextureForLayer(this, m_layerTextureRect, true); + } // SMP flush android::AutoMutex lock(m_atomicSync); - if (m_reservedTexture && m_reservedTexture != reservedTexture) { - m_reservedTexture->release(this); + // we set the reservedTexture if it's different from the drawing texture + if (m_reservedTexture != reservedTexture && + ((m_reservedTexture != m_drawingTexture) || + (m_reservedTexture == 0 && m_drawingTexture == 0))) { + if (m_reservedTexture) + m_reservedTexture->release(this); m_reservedTexture = reservedTexture; } } @@ -590,11 +618,16 @@ void LayerAndroid::createGLTextures() LayerTexture* reservedTexture = m_reservedTexture; if (!reservedTexture) - reservedTexture = TilesManager::instance()->createTextureForLayer(this); + reservedTexture = TilesManager::instance()->createTextureForLayer(this, m_layerTextureRect); if (!reservedTexture) return; + // SMP flush + m_atomicSync.lock(); + m_reservedTexture = reservedTexture; + m_atomicSync.unlock(); + if (reservedTexture && (reservedTexture != m_drawingTexture) && reservedTexture->isReady()) { @@ -608,11 +641,6 @@ void LayerAndroid::createGLTextures() if (!needsScheduleRepaint(reservedTexture)) return; - // SMP flush - m_atomicSync.lock(); - m_reservedTexture = reservedTexture; - m_atomicSync.unlock(); - XLOG("We schedule a paint for layer %d, because isReady %d or m_dirty %d, using texture %x", uniqueId(), m_reservedTexture->isReady(), m_dirty, m_reservedTexture); PaintLayerOperation* operation = new PaintLayerOperation(this); @@ -655,7 +683,13 @@ bool LayerAndroid::drawGL(SkMatrix& matrix) if (prepareContext() && m_drawingTexture) { TextureInfo* textureInfo = m_drawingTexture->consumerLock(); if (textureInfo && m_drawingTexture->isReady()) { - TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect, + SkRect bounds; + IntRect textureRect = m_drawingTexture->rect(); + bounds.set(0, 0, textureRect.width(), textureRect.height()); + // move the drawing depending on where the texture is on the layer + TransformationMatrix m = drawTransform(); + m.translate(textureRect.x(), textureRect.y()); + TilesManager::instance()->shader()->drawLayerQuad(m, bounds, textureInfo->m_textureId, m_drawOpacity); } @@ -709,7 +743,6 @@ void LayerAndroid::paintBitmapGL() // can be updated by other threads without consequence. m_atomicSync.lock(); LayerTexture* texture = m_reservedTexture; - float scale = m_scale; if (!texture) { m_atomicSync.unlock(); @@ -739,10 +772,14 @@ void LayerAndroid::paintBitmapGL() XLOG("LayerAndroid %d paintBitmapGL WE ARE PAINTING", uniqueId()); SkCanvas* canvas = texture->canvas(); + float scale = texture->scale(); + + IntRect textureRect = texture->rect(); canvas->save(); canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); canvas->scale(scale, scale); + canvas->translate(-textureRect.x(), -textureRect.y()); contentDraw(canvas); canvas->restore(); diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h index 41bd9ef..95f8547 100644 --- a/WebCore/platform/graphics/android/LayerAndroid.h +++ b/WebCore/platform/graphics/android/LayerAndroid.h @@ -94,7 +94,7 @@ public: virtual ~LayerAndroid(); // TextureOwner methods - virtual void removeTexture(); + virtual void removeTexture(BackedDoubleBufferedTexture* texture); LayerTexture* texture() { return m_reservedTexture; } virtual TiledPage* page() { return 0; } @@ -294,6 +294,9 @@ private: LayerTexture* m_drawingTexture; LayerTexture* m_reservedTexture; + // rect used to query TilesManager for the right texture + IntRect m_layerTextureRect; + // used to signal that the tile is out-of-date and needs to be redrawn bool m_dirty; unsigned int m_pictureUsed; diff --git a/WebCore/platform/graphics/android/LayerTexture.h b/WebCore/platform/graphics/android/LayerTexture.h index 959978f..3654476 100644 --- a/WebCore/platform/graphics/android/LayerTexture.h +++ b/WebCore/platform/graphics/android/LayerTexture.h @@ -27,6 +27,7 @@ #define LayerTexture_h #include "BackedDoubleBufferedTexture.h" +#include "IntRect.h" namespace WebCore { @@ -36,9 +37,11 @@ class LayerTexture : public BackedDoubleBufferedTexture { SkBitmap::Config config = SkBitmap::kARGB_8888_Config) : BackedDoubleBufferedTexture(w, h, config) , m_id(0) + , m_scale(1) , m_pictureUsed(0) , m_textureUpdates(0) {} + virtual ~LayerTexture() {}; int id() { return m_id; } void setId(int id) { m_id = id; } @@ -47,11 +50,17 @@ class LayerTexture : public BackedDoubleBufferedTexture { void setPictureUsed(unsigned pictureUsed) { m_pictureUsed = pictureUsed; } bool isReady(); virtual void producerUpdate(TextureInfo* textureInfo); + void setRect(const IntRect& r) { m_rect = r; } + IntRect& rect() { return m_rect; } + float scale() { return m_scale; } + void setScale(float scale) { m_scale = scale; } private: void update(); int m_id; + IntRect m_rect; + float m_scale; unsigned int m_pictureUsed; unsigned int m_textureUpdates; }; diff --git a/WebCore/platform/graphics/android/ShaderProgram.cpp b/WebCore/platform/graphics/android/ShaderProgram.cpp index f61186a..dc6577c 100644 --- a/WebCore/platform/graphics/android/ShaderProgram.cpp +++ b/WebCore/platform/graphics/android/ShaderProgram.cpp @@ -231,6 +231,14 @@ void ShaderProgram::clip(const FloatRect& clip) m_clipRect = clip; } +IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect) +{ + IntRect viewport(m_viewport.fLeft, m_viewport.fTop, + m_viewport.width(), m_viewport.height()); + viewport.intersect(rect); + return viewport; +} + void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix, SkRect& geometry, int textureId, float opacity) { diff --git a/WebCore/platform/graphics/android/ShaderProgram.h b/WebCore/platform/graphics/android/ShaderProgram.h index 6508fdb..68cc560 100644 --- a/WebCore/platform/graphics/android/ShaderProgram.h +++ b/WebCore/platform/graphics/android/ShaderProgram.h @@ -44,6 +44,7 @@ class ShaderProgram { FloatRect clipRectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size); void clip(const FloatRect& rect); + IntRect clippedRectWithViewport(const IntRect& rect); private: GLuint loadShader(GLenum shaderType, const char* pSource); diff --git a/WebCore/platform/graphics/android/TextureOwner.h b/WebCore/platform/graphics/android/TextureOwner.h index 959b2bd..7b0673d 100644 --- a/WebCore/platform/graphics/android/TextureOwner.h +++ b/WebCore/platform/graphics/android/TextureOwner.h @@ -29,11 +29,12 @@ namespace WebCore { class TiledPage; +class BackedDoubleBufferedTexture; class TextureOwner { public: virtual ~TextureOwner() {} - virtual void removeTexture() = 0; + virtual void removeTexture(BackedDoubleBufferedTexture* texture) = 0; virtual TiledPage* page() = 0; }; diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp index a1f514f..62cadc3 100644 --- a/WebCore/platform/graphics/android/TexturesGenerator.cpp +++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp @@ -116,6 +116,10 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter) // when we return our caller can be sure that there is no more operations // in the queue matching the given filter. mRequestedOperationsLock.lock(); + if (!m_waitForCompletion) { + mRequestedOperationsLock.unlock(); + return; // operation treated + } mRequestedOperationsCond.wait(mRequestedOperationsLock); m_waitForCompletion = false; mRequestedOperationsLock.unlock(); diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp index d6e868d..1655016 100644 --- a/WebCore/platform/graphics/android/TilesManager.cpp +++ b/WebCore/platform/graphics/android/TilesManager.cpp @@ -230,19 +230,17 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner) return 0; } -LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer) +LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer, + const IntRect& rect, + bool any) { - SkSize layerSize; - layerSize.fWidth = static_cast<int>( - layer->getSize().fWidth * layer->getScale()); - layerSize.fHeight = static_cast<int>( - layer->getSize().fHeight * layer->getScale()); - android::Mutex::Autolock lock(m_texturesLock); for (unsigned int i = 0; i< m_layersTextures.size(); i++) { if (m_layersTextures[i]->id() != layer->uniqueId()) continue; - if (layerSize != m_layersTextures[i]->getSize()) + if (!any && rect != m_layersTextures[i]->rect()) + continue; + if (!any && layer->getScale() != m_layersTextures[i]->scale()) continue; XLOG("return layer %d (%x) for tile %d (%x)", @@ -260,12 +258,11 @@ 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 (scale %.2f, w: %.2f, h: %.2f), owner: %x", + 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]->getScale(), m_layersTextures[i]->owner()); } XLOG("<<< print layers textures (%s)", s); @@ -293,7 +290,7 @@ void TilesManager::cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup) // that are not used by the current page XLOG("force removing texture %x for layer %d", texture, textureLayer->uniqueId()); - textureLayer->removeTexture(); + textureLayer->removeTexture(texture); } } @@ -327,10 +324,10 @@ void TilesManager::cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup) XLOG("after cleanup, memory %d", m_layersMemoryUsage); } -LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer) +LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const IntRect& rect) { - int w = static_cast<int>(layer->getWidth() * layer->getScale()); - int h = static_cast<int>(layer->getHeight() * layer->getScale()); + 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: @@ -346,11 +343,16 @@ LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer) if (large) return 0; + if (w == 0 || h == 0) // empty layer + return 0; + if (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION) cleanupLayersTextures(layer, true); 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); diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h index 576d508..c09a388 100644 --- a/WebCore/platform/graphics/android/TilesManager.h +++ b/WebCore/platform/graphics/android/TilesManager.h @@ -71,13 +71,15 @@ public: void printLayersTextures(const char* s); void cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup = false); - LayerTexture* getExistingTextureForLayer(LayerAndroid* layer); - LayerTexture* createTextureForLayer(LayerAndroid* layer); + LayerTexture* getExistingTextureForLayer(LayerAndroid* layer, const IntRect& rect, + bool any = false); + LayerTexture* createTextureForLayer(LayerAndroid* layer, const IntRect& rect); void markGeneratorAsReady() { android::Mutex::Autolock lock(m_generatorLock); m_generatorReadyCond.signal(); + m_generatorReady = true; } void printTextures(); @@ -97,7 +99,8 @@ private: void waitForGenerator() { android::Mutex::Autolock lock(m_generatorLock); - m_generatorReadyCond.wait(m_generatorLock); + if (!m_generatorReady) + m_generatorReadyCond.wait(m_generatorLock); } Vector<BackedDoubleBufferedTexture*> m_textures; |