, m_usedLevel(-1)
, m_config(config)
, m_owner(0)
+ , m_delayedReleaseOwner(0)
+ , m_delayedRelease(false)
, m_busy(false)
{
m_size.set(w, h);
void BackedDoubleBufferedTexture::producerRelease()
{
DoubleBufferedTexture::producerRelease();
- android::Mutex::Autolock lock(m_busyLock);
- m_busy = false;
+ setNotBusy();
}
void BackedDoubleBufferedTexture::producerReleaseAndSwap()
{
DoubleBufferedTexture::producerReleaseAndSwap();
+ setNotBusy();
+}
+
+void BackedDoubleBufferedTexture::setNotBusy()
+{
android::Mutex::Autolock lock(m_busyLock);
m_busy = false;
+ if (m_delayedRelease) {
+ if (m_owner == m_delayedReleaseOwner) {
+ m_owner->removeOwned(this);
+ m_owner = 0;
+ }
+ m_delayedRelease = false;
+ m_delayedReleaseOwner = 0;
+ }
}
bool BackedDoubleBufferedTexture::busy()
{
// if the writable texture is busy (i.e. currently being written to) then we
// can't change the owner out from underneath that texture
- android::Mutex::Autolock lock(m_busyLock);
- if (!m_busy) {
+ m_busyLock.lock();
+ bool busy = m_busy;
+ m_busyLock.unlock();
+ if (!busy) {
+ // if we are not busy we can try to remove the texture from the layer;
+ // LayerAndroid::removeTexture() is protected by the same lock as
+ // LayerAndroid::paintBitmapGL(), so either we execute removeTexture()
+ // first and paintBitmapGL() will bail out, or we execute it after,
+ // and paintBitmapGL() will mark the texture as busy before
+ // relinquishing the lock. LayerAndroid::removeTexture() will call
+ // BackedDoubleBufferedTexture::release(), which will then do nothing
+ // if the texture is busy and we then don't return true.
+ bool proceed = true;
if (m_owner && m_owner != owner)
- m_owner->removeTexture(this);
- m_owner = owner;
- owner->addOwned(this);
- return true;
+ proceed = m_owner->removeTexture(this);
+
+ if (proceed) {
+ m_owner = owner;
+ owner->addOwned(this);
+ return true;
+ }
}
return false;
}
-void BackedDoubleBufferedTexture::release(TextureOwner* owner)
+bool BackedDoubleBufferedTexture::release(TextureOwner* owner)
{
+ android::Mutex::Autolock lock(m_busyLock);
if (m_owner == owner) {
- m_owner->removeOwned(this);
- m_owner = 0;
+ if (!m_busy) {
+ m_owner->removeOwned(this);
+ m_owner = 0;
+ return true;
+ } else {
+ m_delayedRelease = true;
+ m_delayedReleaseOwner = owner;
+ }
}
-
+ return false;
}
} // namespace WebCore
// allows consumer thread to assign ownership of the texture to the tile. It
// returns false if ownership cannot be transferred because the tile is busy
bool acquire(TextureOwner* owner);
- void release(TextureOwner* owner);
+ bool release(TextureOwner* owner);
// set the texture owner if not busy. Return false if busy, true otherwise.
bool setOwner(TextureOwner* owner);
SkCanvas* canvas(); // only used by the producer thread
bool busy();
+ void setNotBusy();
const SkSize& getSize() const { return m_size; }
SkBitmap::Config m_config;
TextureOwner* m_owner;
+ // When trying to release a texture, we may delay this if the texture is
+ // currently used (busy being painted). We use the following two variables
+ // to do so in setNotBusy()
+ TextureOwner* m_delayedReleaseOwner;
+ bool m_delayedRelease;
+
// This values signals that the texture is currently in use by the consumer.
// This allows us to prevent the owner of the texture from changing while the
// consumer is holding a lock on the texture.
m_texture = texture;
}
-void BaseTile::removeTexture(BackedDoubleBufferedTexture* texture)
+bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture)
{
XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page);
// We update atomically, so paintBitmap() can see the correct value
android::AutoMutex lock(m_atomicSync);
if (m_texture == texture)
m_texture = 0;
+ return true;
}
void BaseTile::setScale(float scale)
BackedDoubleBufferedTexture* texture() { return m_texture; }
// TextureOwner implementation
- virtual void removeTexture(BackedDoubleBufferedTexture* texture);
+ virtual bool removeTexture(BackedDoubleBufferedTexture* texture);
virtual TiledPage* page() { return m_page; }
private:
// We only update the layers if we are not currently
// waiting for a tiledPage to be painted
if (m_baseLayerUpdate) {
+ layer->safeRef();
m_currentBaseLayer->safeUnref();
m_currentBaseLayer = layer;
- m_currentBaseLayer->safeRef();
}
inval(rect);
}
void GLWebViewState::unlockBaseLayerUpdate() {
m_baseLayerUpdate = true;
android::Mutex::Autolock lock(m_baseLayerLock);
+ m_baseLayer->safeRef();
m_currentBaseLayer->safeUnref();
m_currentBaseLayer = m_baseLayer;
- m_currentBaseLayer->safeRef();
inval(m_invalidateRect);
IntRect empty;
m_invalidateRect = empty;
m_tiledPageB->updateBaseTileSize();
}
+bool GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, float scale, SkColor color)
+{
+ m_baseLayerLock.lock();
+ BaseLayerAndroid* baseLayer = m_currentBaseLayer;
+ baseLayer->safeRef();
+ m_baseLayerLock.unlock();
+ if (!baseLayer)
+ return false;
+ bool ret = baseLayer->drawGL(rect, viewport, scale, color);
+ baseLayer->safeUnref();
+ return ret;
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)
void setBackgroundColor(SkColor color) { m_backgroundColor = color; }
SkColor getBackgroundColor() { return m_backgroundColor; }
+ bool drawGL(IntRect& rect, SkRect& viewport,
+ float scale, SkColor color = SK_ColorWHITE);
+
private:
void inval(const IntRect& rect); // caller must hold m_baseLayerLock
#endif
}
-void LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture)
+bool LayerAndroid::removeTexture(BackedDoubleBufferedTexture* 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)
- m_drawingTexture->release(this);
+ textureReleased &= m_drawingTexture->release(this);
if (m_reservedTexture &&
m_reservedTexture != m_drawingTexture)
- m_reservedTexture->release(this);
+ textureReleased &= m_reservedTexture->release(this);
} else {
if (m_drawingTexture && m_drawingTexture == texture)
- m_drawingTexture->release(this);
+ textureReleased &= m_drawingTexture->release(this);
if (m_reservedTexture &&
m_reservedTexture == texture &&
m_reservedTexture != m_drawingTexture)
- m_reservedTexture->release(this);
+ textureReleased &= m_reservedTexture->release(this);
}
if (m_drawingTexture && m_drawingTexture->owner() != this)
m_drawingTexture = 0;
if (m_reservedTexture && m_reservedTexture->owner() != this)
m_reservedTexture = 0;
+ return textureReleased;
}
LayerAndroid::~LayerAndroid()
// 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.
+ // destroyed immediately.
texture->producerAcquireContext();
TextureInfo* textureInfo = texture->producerLock();
m_atomicSync.unlock();
virtual ~LayerAndroid();
// TextureOwner methods
- virtual void removeTexture(BackedDoubleBufferedTexture* texture);
+ virtual bool removeTexture(BackedDoubleBufferedTexture* texture);
LayerTexture* texture() { return m_reservedTexture; }
virtual TiledPage* page() { return 0; }
class TextureOwner {
public:
virtual ~TextureOwner();
- virtual void removeTexture(BackedDoubleBufferedTexture* texture) = 0;
+ virtual bool removeTexture(BackedDoubleBufferedTexture* texture) = 0;
virtual TiledPage* page() = 0;
void addOwned(BackedDoubleBufferedTexture*);
SkRect visibleRect;
calcOurContentVisibleRect(&visibleRect);
+
m_viewImpl->setVisibleScreenWidth(visibleRect.width());
m_viewImpl->setVisibleScreenHeight(visibleRect.height());
- bool ret = m_baseLayer->drawGL(viewRect, visibleRect, scale);
+
+ bool ret = m_glWebViewState->drawGL(viewRect, visibleRect, scale);
+
if (ret || m_glWebViewState->currentPictureCounter() != pic)
return true;
#endif