summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
authorNicolas Roard <nicolas@android.com>2011-01-16 18:27:55 -0800
committerNicolas Roard <nicolas@android.com>2011-01-17 13:21:39 -0800
commit1a8134698fa0b94387482fb4b45341faa8fe6a38 (patch)
treebdd06ce24713cce2168356f2289665f88a732492 /WebCore/platform
parent2a72fb6cf823503e177d0ff93ee6fac5df9f19f8 (diff)
downloadexternal_webkit-1a8134698fa0b94387482fb4b45341faa8fe6a38.zip
external_webkit-1a8134698fa0b94387482fb4b45341faa8fe6a38.tar.gz
external_webkit-1a8134698fa0b94387482fb4b45341faa8fe6a38.tar.bz2
Implement re-scaling for layers
Change-Id: I1f998387831207d00f27945ee4e456f81ff6f6e2 Change-Id: I7efcccfd9a4374061300058d4c48fa82a973829a
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp6
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h3
-rw-r--r--WebCore/platform/graphics/android/BaseLayerAndroid.cpp20
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp148
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h25
-rw-r--r--WebCore/platform/graphics/android/PaintLayerOperation.cpp19
-rw-r--r--WebCore/platform/graphics/android/PaintLayerOperation.h16
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.cpp15
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.h2
-rw-r--r--WebCore/platform/graphics/android/TilesManager.cpp93
-rw-r--r--WebCore/platform/graphics/android/TilesManager.h9
11 files changed, 272 insertions, 84 deletions
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
index 12e0436..ddfa9a0 100644
--- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
+++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
@@ -98,6 +98,12 @@ void BackedDoubleBufferedTexture::producerReleaseAndSwap()
m_busy = false;
}
+bool BackedDoubleBufferedTexture::busy()
+{
+ android::Mutex::Autolock lock(m_busyLock);
+ return m_busy;
+}
+
void BackedDoubleBufferedTexture::producerUpdate(TextureInfo* textureInfo)
{
// no need to upload a texture since the bitmap is empty
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
index 844715d..0b62224 100644
--- a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
+++ b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.h
@@ -76,8 +76,7 @@ public:
TextureOwner* owner() { return m_owner; } // only used by the consumer thread
SkCanvas* canvas() { return m_canvas; } // only used by the producer thread
- // This is to be only used for debugging on the producer thread
- bool busy() { return m_busy; }
+ bool busy();
const SkSize& getSize() const { return m_size; }
diff --git a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
index b84831d..9ed967f 100644
--- a/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/BaseLayerAndroid.cpp
@@ -272,11 +272,23 @@ bool BaseLayerAndroid::drawGL(IntRect& viewRect, SkRect& visibleRect,
#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
+ // we can use the future scale instead of the current scale to request
+ // new textures. After a transition time, the scaleRequestState will be
+ // reset and the current scale will be set to the future scale.
+ float scale = m_glWebViewState->currentScale();
+ if (m_glWebViewState->scaleRequestState() == GLWebViewState::kReceivedNewScale) {
+ scale = m_glWebViewState->futureScale();
+ }
+ compositedRoot->setScale(scale);
compositedRoot->reserveGLTextures();
- // Now that we marked the textures being used, we delete the unnecessary
- // ones to make space...
- TilesManager::instance()->cleanupLayersTextures();
- // Finally do another pass to create new textures if needed
+ // Now that we marked the textures being used, we delete
+ // the unnecessary ones to make space...
+ TilesManager::instance()->cleanupLayersTextures(compositedRoot);
+ // Finally do another pass to create new textures and schedule
+ // repaints if needed
compositedRoot->createGLTextures();
if (compositedRoot->drawGL(matrix))
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
index aec039d..64060f7 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.cpp
+++ b/WebCore/platform/graphics/android/LayerAndroid.cpp
@@ -75,8 +75,10 @@ LayerAndroid::LayerAndroid(bool isRootLayer) : SkLayer(),
m_contentsImage(0),
m_extra(0),
m_uniqueId(++gUniqueId),
- m_texture(0),
- m_pictureUsed(0)
+ m_drawingTexture(0),
+ m_reservedTexture(0),
+ m_pictureUsed(0),
+ m_scale(1)
{
m_backgroundColor = 0;
@@ -91,7 +93,8 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
m_haveClip(layer.m_haveClip),
m_extra(0), // deliberately not copied
m_uniqueId(layer.m_uniqueId),
- m_texture(0)
+ m_drawingTexture(0),
+ m_reservedTexture(0)
{
m_isFixed = layer.m_isFixed;
m_contentsImage = layer.m_contentsImage;
@@ -119,6 +122,7 @@ LayerAndroid::LayerAndroid(const LayerAndroid& layer) : SkLayer(layer),
m_childrenTransform = layer.m_childrenTransform;
m_dirty = layer.m_dirty;
m_pictureUsed = layer.m_pictureUsed;
+ m_scale = layer.m_scale;
for (int i = 0; i < layer.countChildren(); i++)
addChild(layer.getChild(i)->copy())->unref();
@@ -138,7 +142,9 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
m_contentsImage(0),
m_extra(0),
m_uniqueId(-1),
- m_texture(0)
+ m_drawingTexture(0),
+ m_reservedTexture(0),
+ m_scale(1)
{
m_backgroundColor = 0;
m_dirty = false;
@@ -146,10 +152,22 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
gDebugLayerAndroidInstances++;
}
+void LayerAndroid::removeTexture()
+{
+ XLOG("remove texture (m_drawingTexture: %x, m_reservedTexture: %x)",
+ m_drawingTexture, m_reservedTexture);
+ 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;
+}
+
LayerAndroid::~LayerAndroid()
{
- if (m_texture)
- m_texture->release(this);
+ removeTexture();
removeChildren();
m_contentsImage->safeUnref();
m_recordingPicture->safeUnref();
@@ -549,12 +567,15 @@ void LayerAndroid::reserveGLTextures()
for (int i = 0; i < count; i++)
this->getChild(i)->reserveGLTextures();
- if (needsTexture()) {
- LayerTexture* texture;
- texture = TilesManager::instance()->getExistingTextureForLayer(this);
- // SMP flush
- android::AutoMutex lock(m_atomicSync);
- m_texture = texture;
+ LayerTexture* reservedTexture = 0;
+ if (needsTexture())
+ reservedTexture = TilesManager::instance()->getExistingTextureForLayer(this);
+
+ // SMP flush
+ android::AutoMutex lock(m_atomicSync);
+ if (m_reservedTexture && m_reservedTexture != reservedTexture) {
+ m_reservedTexture->release(this);
+ m_reservedTexture = reservedTexture;
}
}
@@ -564,46 +585,56 @@ void LayerAndroid::createGLTextures()
for (int i = 0; i < count; i++)
this->getChild(i)->createGLTextures();
- if (needsTexture() && !m_texture) {
- LayerTexture* texture;
- texture = TilesManager::instance()->createTextureForLayer(this);
- // SMP flush + keep dirty bit in sync
- android::AutoMutex lock(m_atomicSync);
- m_texture = texture;
- m_dirty = true;
+ if (!needsTexture())
+ return;
+
+ LayerTexture* reservedTexture = m_reservedTexture;
+ if (!reservedTexture)
+ reservedTexture = TilesManager::instance()->createTextureForLayer(this);
+
+ if (!reservedTexture)
+ return;
+
+ if (reservedTexture &&
+ (reservedTexture != m_drawingTexture) &&
+ reservedTexture->isReady()) {
+ if (m_drawingTexture) {
+ TilesManager::instance()->removeOperationsForTexture(m_drawingTexture);
+ m_drawingTexture->release(this);
+ }
+ m_drawingTexture = reservedTexture;
}
- checkForObsolescence();
+ 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);
+ TilesManager::instance()->scheduleOperation(operation);
}
-void LayerAndroid::checkForObsolescence()
+bool LayerAndroid::needsScheduleRepaint(LayerTexture* texture)
{
- m_atomicSync.lock();
- if (!m_texture) {
- m_atomicSync.unlock();
- return;
- }
+ if (!texture)
+ return false;
- if (!m_pictureUsed || m_texture->pictureUsed() != m_pictureUsed) {
+ if (!m_pictureUsed || texture->pictureUsed() != m_pictureUsed) {
XLOG("We mark layer %d as dirty because: m_pictureUsed(%d == 0?), texture picture used %x",
- uniqueId(), m_pictureUsed, m_texture->pictureUsed());
- m_texture->setPictureUsed(m_pictureUsed);
+ uniqueId(), m_pictureUsed, texture->pictureUsed());
+ texture->setPictureUsed(m_pictureUsed);
m_dirty = true;
}
- if (!m_texture->isReady())
+ if (!texture->isReady())
m_dirty = true;
- bool dirty = m_dirty;
- m_atomicSync.unlock();
-
- if (!dirty)
- return;
-
- XLOG("We schedule a paint for layer %d, because isReady %d or m_dirty %d",
- uniqueId(), m_texture->isReady(), m_dirty);
- PaintLayerOperation* operation = new PaintLayerOperation(this);
- TilesManager::instance()->scheduleOperation(operation);
+ return m_dirty;
}
static inline bool compareLayerZ(const LayerAndroid* a, const LayerAndroid* b)
@@ -621,14 +652,14 @@ bool LayerAndroid::drawGL(SkMatrix& matrix)
TilesManager::instance()->shader()->clip(m_clippingRect);
- if (prepareContext() && m_texture) {
- TextureInfo* textureInfo = m_texture->consumerLock();
- if (textureInfo && m_texture->isReady()) {
+ if (prepareContext() && m_drawingTexture) {
+ TextureInfo* textureInfo = m_drawingTexture->consumerLock();
+ if (textureInfo && m_drawingTexture->isReady()) {
TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect,
textureInfo->m_textureId,
m_drawOpacity);
}
- m_texture->consumerRelease();
+ m_drawingTexture->consumerRelease();
}
// When the layer is dirty, the UI thread should be notified to redraw.
@@ -660,24 +691,44 @@ bool LayerAndroid::drawChildrenGL(SkMatrix& matrix)
return askPaint;
}
+void LayerAndroid::setScale(float scale)
+{
+ int count = this->countChildren();
+ for (int i = 0; i < count; i++)
+ this->getChild(i)->setScale(scale);
+
+ android::AutoMutex lock(m_atomicSync);
+ m_scale = scale;
+}
+
// This is called from the texture generation thread
void LayerAndroid::paintBitmapGL()
{
- XLOG("LayerAndroid paintBitmapGL (layer %d)", uniqueId());
// 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_texture;
- m_atomicSync.unlock();
+ LayerTexture* texture = m_reservedTexture;
+ float scale = m_scale;
if (!texture) {
+ m_atomicSync.unlock();
XLOG("Layer %d doesn't have a texture!", uniqueId());
return;
}
+ XLOG("LayerAndroid paintBitmapGL (layer %d), texture used %x", uniqueId(), texture);
+
+ // 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
+ // destroy 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)
@@ -689,8 +740,11 @@ void LayerAndroid::paintBitmapGL()
XLOG("LayerAndroid %d paintBitmapGL WE ARE PAINTING", uniqueId());
SkCanvas* canvas = texture->canvas();
+ canvas->save();
canvas->drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode);
+ canvas->scale(scale, scale);
contentDraw(canvas);
+ canvas->restore();
XLOG("LayerAndroid %d paintBitmapGL PAINTING DONE, updating the texture", uniqueId());
m_atomicSync.lock();
diff --git a/WebCore/platform/graphics/android/LayerAndroid.h b/WebCore/platform/graphics/android/LayerAndroid.h
index 76b4cb8..41bd9ef 100644
--- a/WebCore/platform/graphics/android/LayerAndroid.h
+++ b/WebCore/platform/graphics/android/LayerAndroid.h
@@ -94,11 +94,9 @@ public:
virtual ~LayerAndroid();
// TextureOwner methods
- virtual void removeTexture()
- {
- android::AutoMutex lock(m_atomicSync);
- m_texture = 0;
- }
+ virtual void removeTexture();
+
+ LayerTexture* texture() { return m_reservedTexture; }
virtual TiledPage* page() { return 0; }
static int instancesCount();
@@ -111,8 +109,10 @@ public:
void createGLTextures();
virtual bool needsTexture();
- void checkForObsolescence();
+ bool needsScheduleRepaint(LayerTexture* texture);
+ void setScale(float scale);
+ float getScale() { return m_scale; }
virtual bool drawGL(SkMatrix&);
bool drawChildrenGL(SkMatrix&);
virtual void paintBitmapGL();
@@ -285,12 +285,21 @@ private:
DrawExtra* m_extra;
int m_uniqueId;
- // GL textures management
- LayerTexture* m_texture;
+ // 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;
+
// used to signal that the tile is out-of-date and needs to be redrawn
bool m_dirty;
unsigned int m_pictureUsed;
+ float m_scale;
+
// This mutex serves two purposes. (1) It ensures that certain operations
// happen atomically and (2) it makes sure those operations are synchronized
// across all threads and cores.
diff --git a/WebCore/platform/graphics/android/PaintLayerOperation.cpp b/WebCore/platform/graphics/android/PaintLayerOperation.cpp
index a3ef148..dd81d9a 100644
--- a/WebCore/platform/graphics/android/PaintLayerOperation.cpp
+++ b/WebCore/platform/graphics/android/PaintLayerOperation.cpp
@@ -50,7 +50,14 @@ SkLayer* PaintLayerOperation::baseLayer()
return m_layer->getRootLayer();
}
-bool PaintLayerFilter::check(QueuedOperation* operation)
+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);
@@ -59,3 +66,13 @@ bool PaintLayerFilter::check(QueuedOperation* operation)
}
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/WebCore/platform/graphics/android/PaintLayerOperation.h b/WebCore/platform/graphics/android/PaintLayerOperation.h
index d393ac5..74e87af 100644
--- a/WebCore/platform/graphics/android/PaintLayerOperation.h
+++ b/WebCore/platform/graphics/android/PaintLayerOperation.h
@@ -33,6 +33,7 @@ class SkLayer;
namespace WebCore {
class LayerAndroid;
+class LayerTexture;
class PaintLayerOperation : public QueuedOperation {
public:
@@ -43,20 +44,31 @@ class PaintLayerOperation : public QueuedOperation {
virtual bool operator==(const QueuedOperation* operation);
virtual void run();
SkLayer* baseLayer();
+ LayerAndroid* layer() { return m_layer; }
+ LayerTexture* texture();
private:
LayerAndroid* m_layer;
};
-class PaintLayerFilter : public OperationFilter {
+class PaintLayerBaseFilter : public OperationFilter {
public:
- PaintLayerFilter(SkLayer* layer) : m_baseLayer(layer) {}
+ PaintLayerBaseFilter(SkLayer* layer) : m_baseLayer(layer) {}
virtual bool check(QueuedOperation* operation);
private:
SkLayer* m_baseLayer;
};
+class PaintLayerTextureFilter : public OperationFilter {
+ public:
+ PaintLayerTextureFilter(LayerTexture* texture) : m_texture(texture) {}
+ virtual bool check(QueuedOperation* operation);
+
+ private:
+ LayerTexture* m_texture;
+};
+
}
#endif // PaintLayerOperation_h
diff --git a/WebCore/platform/graphics/android/TexturesGenerator.cpp b/WebCore/platform/graphics/android/TexturesGenerator.cpp
index 289665d..a1f514f 100644
--- a/WebCore/platform/graphics/android/TexturesGenerator.cpp
+++ b/WebCore/platform/graphics/android/TexturesGenerator.cpp
@@ -80,7 +80,12 @@ void TexturesGenerator::removeOperationsForPage(TiledPage* page)
void TexturesGenerator::removeOperationsForBaseLayer(BaseLayerAndroid* layer)
{
- removeOperationsForFilter(new PaintLayerFilter(layer));
+ removeOperationsForFilter(new PaintLayerBaseFilter(layer));
+}
+
+void TexturesGenerator::removeOperationsForTexture(LayerTexture* texture)
+{
+ removeOperationsForFilter(new PaintLayerTextureFilter(texture));
}
void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
@@ -106,10 +111,10 @@ void TexturesGenerator::removeOperationsForFilter(OperationFilter* filter)
if (!m_waitForCompletion)
return;
- // At this point, it means that we are currently painting a operation that
- // we want to be removed -- we should wait until it is painted, so that
- // when we return our caller can be sure that there is no more TileSet
- // in the queue for that TiledPage and can safely deallocate the BaseTiles.
+ // At this point, it means that we are currently executing an operation that
+ // we want to be removed -- we should wait until it is done, so that
+ // when we return our caller can be sure that there is no more operations
+ // in the queue matching the given filter.
mRequestedOperationsLock.lock();
mRequestedOperationsCond.wait(mRequestedOperationsLock);
m_waitForCompletion = false;
diff --git a/WebCore/platform/graphics/android/TexturesGenerator.h b/WebCore/platform/graphics/android/TexturesGenerator.h
index 0e40e4a..d98eb5b 100644
--- a/WebCore/platform/graphics/android/TexturesGenerator.h
+++ b/WebCore/platform/graphics/android/TexturesGenerator.h
@@ -28,6 +28,7 @@
#if USE(ACCELERATED_COMPOSITING)
+#include "LayerTexture.h"
#include "QueuedOperation.h"
#include "TileSet.h"
#include "TiledPage.h"
@@ -50,6 +51,7 @@ public:
void removeOperationsForPage(TiledPage* page);
void removeOperationsForBaseLayer(BaseLayerAndroid* layer);
+ void removeOperationsForTexture(LayerTexture* texture);
void removeOperationsForFilter(OperationFilter* filter);
void scheduleOperation(QueuedOperation* operation);
diff --git a/WebCore/platform/graphics/android/TilesManager.cpp b/WebCore/platform/graphics/android/TilesManager.cpp
index 3e174d1..d6e868d 100644
--- a/WebCore/platform/graphics/android/TilesManager.cpp
+++ b/WebCore/platform/graphics/android/TilesManager.cpp
@@ -84,6 +84,10 @@ TilesManager::TilesManager()
m_pixmapsGenerationThread = new TexturesGenerator();
m_pixmapsGenerationThread->run("TexturesGenerator");
+
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_maxTextureSize);
+ m_totalMaxTextureSize = m_maxTextureSize * m_maxTextureSize * BYTES_PER_PIXEL;
+ XLOG("Max texture size %d", m_maxTextureSize);
}
// Has to be run on the texture generation threads
@@ -228,11 +232,17 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner)
LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer)
{
+ 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 (layer->getSize() != m_layersTextures[i]->getSize())
+ if (layerSize != m_layersTextures[i]->getSize())
continue;
XLOG("return layer %d (%x) for tile %d (%x)",
@@ -248,46 +258,101 @@ LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer)
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, owner: %x", i, s, m_layersTextures[i],
- m_layersTextures[i]->id(), m_layersTextures[i]->owner());
+ XLOG("[%d] %s, texture %x for layer %d (scale %.2f, 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);
#endif
}
-void TilesManager::cleanupLayersTextures(bool forceCleanup)
+void TilesManager::cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup)
{
android::Mutex::Autolock lock(m_texturesLock);
+ SkLayer* rootLayer = layer->getRootLayer();
#ifdef DEBUG
- printLayersTextures("cleanup");
+ 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(); i++) {
+ for (unsigned int i = 0; i< m_layersTextures.size();) {
LayerTexture* texture = m_layersTextures[i];
- if (forceCleanup)
- texture->setOwner(0);
+ 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();
+ }
+ }
- if (!texture->owner()) {
+ // 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++;
}
}
+ printLayersTextures("after cleanup");
+ XLOG("after cleanup, memory %d", m_layersMemoryUsage);
}
LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer)
{
- int w = layer->getWidth();
- int h = layer->getHeight();
- int size = w * h * BYTES_PER_PIXEL;
+ int w = static_cast<int>(layer->getWidth() * layer->getScale());
+ int h = static_cast<int>(layer->getHeight() * layer->getScale());
+ unsigned int size = w * h * BYTES_PER_PIXEL;
+
+ // We will not allocate textures that:
+ // 1) cannot be handled by the graphic card (m_maxTextureSize &
+ // m_totalMaxTextureSize)
+ // 2) will make us go past our texture limit (MAX_LAYERS_ALLOCATION)
+
+ bool large = w > m_maxTextureSize || h > m_maxTextureSize || size > m_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 (m_layersMemoryUsage + size > MAX_LAYERS_ALLOCATION)
- cleanupLayersTextures(true);
+ cleanupLayersTextures(layer, true);
- android::Mutex::Autolock lock(m_texturesLock);
LayerTexture* texture = new LayerTexture(w, h);
texture->setId(layer->uniqueId());
+
+ android::Mutex::Autolock lock(m_texturesLock);
m_layersTextures.append(texture);
texture->acquire(layer);
m_layersMemoryUsage += size;
diff --git a/WebCore/platform/graphics/android/TilesManager.h b/WebCore/platform/graphics/android/TilesManager.h
index e69db4c..576d508 100644
--- a/WebCore/platform/graphics/android/TilesManager.h
+++ b/WebCore/platform/graphics/android/TilesManager.h
@@ -55,6 +55,11 @@ public:
m_pixmapsGenerationThread->removeOperationsForBaseLayer(layer);
}
+ void removeOperationsForTexture(LayerTexture* texture)
+ {
+ m_pixmapsGenerationThread->removeOperationsForTexture(texture);
+ }
+
void scheduleOperation(QueuedOperation* operation)
{
m_pixmapsGenerationThread->scheduleOperation(operation);
@@ -65,7 +70,7 @@ public:
BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner);
void printLayersTextures(const char* s);
- void cleanupLayersTextures(bool forceCleanup = false);
+ void cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup = false);
LayerTexture* getExistingTextureForLayer(LayerAndroid* layer);
LayerTexture* createTextureForLayer(LayerAndroid* layer);
@@ -99,6 +104,8 @@ private:
Vector<LayerTexture*> m_layersTextures;
unsigned int m_layersMemoryUsage;
+ GLint m_maxTextureSize;
+ unsigned int m_totalMaxTextureSize;
bool m_generatorReady;