summaryrefslogtreecommitdiffstats
path: root/WebCore
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore')
-rw-r--r--WebCore/page/FrameView.cpp57
-rw-r--r--WebCore/page/FrameView.h7
-rw-r--r--WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp8
-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/BaseTile.cpp5
-rw-r--r--WebCore/platform/graphics/android/BaseTile.h2
-rw-r--r--WebCore/platform/graphics/android/GLWebViewState.cpp8
-rw-r--r--WebCore/platform/graphics/android/GLWebViewState.h3
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.cpp185
-rw-r--r--WebCore/platform/graphics/android/LayerAndroid.h28
-rw-r--r--WebCore/platform/graphics/android/LayerTexture.h9
-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/ShaderProgram.cpp8
-rw-r--r--WebCore/platform/graphics/android/ShaderProgram.h1
-rw-r--r--WebCore/platform/graphics/android/TextureOwner.h3
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.cpp19
-rw-r--r--WebCore/platform/graphics/android/TexturesGenerator.h2
-rw-r--r--WebCore/platform/graphics/android/TilesManager.cpp99
-rw-r--r--WebCore/platform/graphics/android/TilesManager.h18
-rw-r--r--WebCore/rendering/RenderIFrame.cpp7
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp9
23 files changed, 402 insertions, 134 deletions
diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp
index 3154a67..5314a32 100644
--- a/WebCore/page/FrameView.cpp
+++ b/WebCore/page/FrameView.cpp
@@ -143,6 +143,9 @@ FrameView::FrameView(Frame* frame)
, m_deferSetNeedsLayouts(0)
, m_setNeedsLayoutWasDeferred(false)
, m_scrollCorner(0)
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ , m_hasOverflowScroll(false)
+#endif
{
init();
}
@@ -553,11 +556,6 @@ void FrameView::updateCompositingLayers()
RenderView* view = m_frame->contentRenderer();
if (!view)
return;
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- // Enter compositing mode for child frames that have layout dimensions.
- if (hasOverflowScroll())
- enterCompositingMode();
-#endif
// This call will make sure the cached hasAcceleratedCompositing is updated from the pref
view->compositor()->cacheAcceleratedCompositingFlags();
@@ -571,31 +569,6 @@ void FrameView::setNeedsOneShotDrawingSynchronization()
page->chrome()->client()->setNeedsOneShotDrawingSynchronization();
}
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-bool FrameView::hasOverflowScroll() const
-{
-#ifndef ANDROID_FLATTEN_IFRAME
- RenderObject* ownerRenderer = m_frame->ownerRenderer();
- if (!ownerRenderer || !ownerRenderer->isRenderIFrame())
- return false;
- RenderLayer* layer = ownerRenderer->enclosingLayer();
- // Make sure the layer has visible content or descendants.
- if (!layer->hasVisibleContent() && !layer->hasVisibleDescendant())
- return false;
- // If either layout dimension is 0, return false.
- if (!layoutWidth() || !layoutHeight())
- return false;
- ScrollbarMode h, v;
- scrollbarModes(h, v);
- if (h == ScrollbarAlwaysOff || v == ScrollbarAlwaysOff)
- return false;
- if (contentsWidth() <= layoutWidth() && contentsHeight() <= layoutHeight())
- return false;
- return true;
-#endif
- return false;
-}
-#endif
#endif // USE(ACCELERATED_COMPOSITING)
bool FrameView::hasCompositedContent() const
@@ -955,6 +928,30 @@ void FrameView::layout(bool allowSubtree)
InspectorInstrumentation::didLayout(cookie);
m_nestedLayoutCount--;
+#if ENABLE(ANDROID_OVERFLOW_SCROLL) && !defined(ANDROID_FLATTEN_IFRAME)
+ // Reset to false each time we layout in case the overflow status changed.
+ bool hasOverflowScroll = false;
+ RenderObject* ownerRenderer = m_frame->ownerRenderer();
+ if (ownerRenderer && ownerRenderer->isRenderIFrame()) {
+ RenderLayer* layer = ownerRenderer->enclosingLayer();
+ if (layer) {
+ // Some sites use tiny iframes for loading so don't composite those.
+ if (canHaveScrollbars() && layoutWidth() > 1 && layoutHeight() > 1)
+ hasOverflowScroll = layoutWidth() < contentsWidth() || layoutHeight() < contentsHeight();
+ }
+ }
+ if (RenderView* view = m_frame->contentRenderer()) {
+ if (hasOverflowScroll != m_hasOverflowScroll) {
+ if (hasOverflowScroll)
+ enterCompositingMode();
+ else
+ // We are leaving overflow mode so we need to update the layer
+ // tree in case that is the reason we were composited.
+ view->compositor()->scheduleCompositingLayerUpdate();
+ }
+ }
+ m_hasOverflowScroll = hasOverflowScroll;
+#endif
}
void FrameView::addWidgetToUpdate(RenderEmbeddedObject* object)
diff --git a/WebCore/page/FrameView.h b/WebCore/page/FrameView.h
index d56b1ef..1b5b322 100644
--- a/WebCore/page/FrameView.h
+++ b/WebCore/page/FrameView.h
@@ -103,9 +103,9 @@ public:
// Called when changes to the GraphicsLayer hierarchy have to be synchronized with
// content rendered via the normal painting path.
void setNeedsOneShotDrawingSynchronization();
-#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- bool hasOverflowScroll() const;
#endif
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ bool hasOverflowScroll() const { return m_hasOverflowScroll; }
#endif
bool hasCompositedContent() const;
@@ -390,6 +390,9 @@ private:
static double s_initialDeferredRepaintDelayDuringLoading;
static double s_maxDeferredRepaintDelayDuringLoading;
static double s_deferredRepaintDelayIncrementDuringLoading;
+#if ENABLE(ANDROID_OVERFLOW_SCROLL)
+ bool m_hasOverflowScroll;
+#endif
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp b/WebCore/platform/graphics/android/BackedDoubleBufferedTexture.cpp
index 12e0436..3462975 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
@@ -132,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/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/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/GLWebViewState.cpp b/WebCore/platform/graphics/android/GLWebViewState.cpp
index 1c32848..45915e5 100644
--- a/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -63,7 +63,7 @@ int GLWebViewState::count()
}
#endif
-GLWebViewState::GLWebViewState()
+GLWebViewState::GLWebViewState(android::Mutex* buttonMutex)
: m_scaleRequestState(kNoScaleRequest)
, m_currentScale(1)
, m_futureScale(1)
@@ -72,6 +72,7 @@ GLWebViewState::GLWebViewState()
, m_baseLayer(0)
, m_currentPictureCounter(0)
, m_usePageA(true)
+ , m_globalButtonMutex(buttonMutex)
{
m_viewport.setEmpty();
m_futureViewportTileBounds.setEmpty();
@@ -135,8 +136,11 @@ void GLWebViewState::inval(const IntRect& rect)
unsigned int GLWebViewState::paintBaseLayerContent(SkCanvas* canvas)
{
android::Mutex::Autolock lock(m_baseLayerLock);
- if (m_baseLayer)
+ if (m_baseLayer) {
+ m_globalButtonMutex->lock();
m_baseLayer->drawCanvas(canvas);
+ m_globalButtonMutex->unlock();
+ }
return m_currentPictureCounter;
}
diff --git a/WebCore/platform/graphics/android/GLWebViewState.h b/WebCore/platform/graphics/android/GLWebViewState.h
index c627a6e..8d2216e 100644
--- a/WebCore/platform/graphics/android/GLWebViewState.h
+++ b/WebCore/platform/graphics/android/GLWebViewState.h
@@ -152,7 +152,7 @@ public:
};
typedef int32_t GLScaleState;
- GLWebViewState();
+ GLWebViewState(android::Mutex* globalButtonMutex);
~GLWebViewState();
GLScaleState scaleRequestState() const { return m_scaleRequestState; }
void setScaleRequestState(GLScaleState state) { m_scaleRequestState = state; }
@@ -222,6 +222,7 @@ private:
TiledPage* m_tiledPageA;
TiledPage* m_tiledPageB;
SkIRect m_lastInval;
+ android::Mutex* m_globalButtonMutex;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/android/LayerAndroid.cpp b/WebCore/platform/graphics/android/LayerAndroid.cpp
index aec039d..95d4ff4 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,33 @@ LayerAndroid::LayerAndroid(SkPicture* picture) : SkLayer(),
gDebugLayerAndroidInstances++;
}
+void LayerAndroid::removeTexture(BackedDoubleBufferedTexture* aTexture)
+{
+ LayerTexture* texture = static_cast<LayerTexture*>(aTexture);
+ android::AutoMutex lock(m_atomicSync);
+ 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()
{
- if (m_texture)
- m_texture->release(this);
+ removeTexture(0);
removeChildren();
m_contentsImage->safeUnref();
m_recordingPicture->safeUnref();
@@ -521,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()) {
@@ -549,12 +579,31 @@ void LayerAndroid::reserveGLTextures()
for (int i = 0; i < count; i++)
this->getChild(i)->reserveGLTextures();
+ LayerTexture* reservedTexture = 0;
if (needsTexture()) {
- LayerTexture* texture;
- texture = TilesManager::instance()->getExistingTextureForLayer(this);
- // SMP flush
- android::AutoMutex lock(m_atomicSync);
- m_texture = texture;
+ // 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);
+ // 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;
}
}
@@ -564,46 +613,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, m_layerTextureRect);
+
+ if (!reservedTexture)
+ return;
+
+ // SMP flush
+ m_atomicSync.lock();
+ m_reservedTexture = reservedTexture;
+ m_atomicSync.unlock();
+
+ 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;
+
+ 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 +680,20 @@ 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()) {
- TilesManager::instance()->shader()->drawLayerQuad(drawTransform(), rect,
+ if (prepareContext() && m_drawingTexture) {
+ TextureInfo* textureInfo = m_drawingTexture->consumerLock();
+ if (textureInfo && m_drawingTexture->isReady()) {
+ 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);
}
- m_texture->consumerRelease();
+ m_drawingTexture->consumerRelease();
}
// When the layer is dirty, the UI thread should be notified to redraw.
@@ -660,24 +725,43 @@ 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;
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)
@@ -688,9 +772,16 @@ 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();
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..95f8547 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(BackedDoubleBufferedTexture* texture);
+
+ 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,24 @@ 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;
+
+ // 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;
+ 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/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/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/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 289665d..62cadc3 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,11 +111,15 @@ 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();
+ if (!m_waitForCompletion) {
+ mRequestedOperationsLock.unlock();
+ return; // operation treated
+ }
mRequestedOperationsCond.wait(mRequestedOperationsLock);
m_waitForCompletion = false;
mRequestedOperationsLock.unlock();
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..1655016 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
@@ -226,13 +230,17 @@ BackedDoubleBufferedTexture* TilesManager::getAvailableTexture(BaseTile* owner)
return 0;
}
-LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer)
+LayerTexture* TilesManager::getExistingTextureForLayer(LayerAndroid* layer,
+ const IntRect& rect,
+ bool any)
{
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 (!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)",
@@ -248,46 +256,105 @@ 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 (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(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(texture);
+ }
+ }
- 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)
+LayerTexture* TilesManager::createTextureForLayer(LayerAndroid* layer, const IntRect& rect)
{
- int w = layer->getWidth();
- int h = layer->getHeight();
- int size = w * h * BYTES_PER_PIXEL;
+ 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 (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 (w == 0 || h == 0) // empty layer
+ 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());
+ texture->setRect(rect);
+ texture->setScale(layer->getScale());
+
+ 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..c09a388 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,14 +70,16 @@ public:
BackedDoubleBufferedTexture* getAvailableTexture(BaseTile* owner);
void printLayersTextures(const char* s);
- void cleanupLayersTextures(bool forceCleanup = false);
- LayerTexture* getExistingTextureForLayer(LayerAndroid* layer);
- LayerTexture* createTextureForLayer(LayerAndroid* layer);
+ void cleanupLayersTextures(LayerAndroid* layer, bool forceCleanup = false);
+ 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();
@@ -92,13 +99,16 @@ 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;
Vector<LayerTexture*> m_layersTextures;
unsigned int m_layersMemoryUsage;
+ GLint m_maxTextureSize;
+ unsigned int m_totalMaxTextureSize;
bool m_generatorReady;
diff --git a/WebCore/rendering/RenderIFrame.cpp b/WebCore/rendering/RenderIFrame.cpp
index a2cf66c..36d2449 100644
--- a/WebCore/rendering/RenderIFrame.cpp
+++ b/WebCore/rendering/RenderIFrame.cpp
@@ -266,6 +266,13 @@ bool RenderIFrame::requiresAcceleratedCompositing() const
if (!node() || !node()->hasTagName(iframeTag))
return false;
+#if PLATFORM(ANDROID)
+ // XXX: Bug submitted to webkit.org
+ // https://bugs.webkit.org/show_bug.cgi?id=52655
+ if (style()->visibility() != VISIBLE)
+ return false;
+#endif
+
// If the contents of the iframe are composited, then we have to be as well.
HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node());
if (Document* contentDocument = element->contentDocument()) {
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index 654f6e6..0877468 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -591,13 +591,12 @@ void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, O
if (layer->isFixed())
compositingState.m_fixedSibling = true;
- if (!willBeComposited && compositingState.m_fixedSibling)
+ if (!willBeComposited && compositingState.m_fixedSibling) {
layer->setMustOverlapCompositedLayers(true);
-
- if (willBeComposited || compositingState.m_fixedSibling) {
-#else
- if (willBeComposited) {
+ willBeComposited = true;
+ }
#endif
+ if (willBeComposited) {
// Tell the parent it has compositing descendants.
compositingState.m_subtreeIsCompositing = true;
// This layer now acts as the ancestor for kids.