https://bugs.webkit.org/show_bug.cgi?id=72630
Patch by David Reveman <reveman@chromium.org> on 2011-11-17
Reviewed by James Robinson.
Source/WebCore:
Layer property changes during paintContent() can leave the layer
in an invalid state as paintContentsIfDirty() has been called
without a matching updateCompositorResources() call. Removing
conditionals around these calls ensure they are balanced.
This patch is tested by the following unit test:
- CCLayerTreeHostTestOpacityChange.runMultiThread
* platform/graphics/chromium/ContentLayerChromium.cpp:
(WebCore::ContentLayerChromium::paintContentsIfDirty):
* platform/graphics/chromium/VideoLayerChromium.cpp:
(WebCore::VideoLayerChromium::updateCompositorResources):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::paintMaskAndReplicaForRenderSurface):
(WebCore::CCLayerTreeHost::paintLayerContents):
(WebCore::CCLayerTreeHost::updateCompositorResources):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
Source/WebKit/chromium:
Add test that check if calls to paintContentsIfDirty() and
updateCompositorResources() are balanced when layer opacity
changes during paintContent().
* tests/CCLayerTreeHostTest.cpp:
(WTF::CCLayerTreeHostTest::layerTreeHost):
(WTF::TestOpacityChangeLayerDelegate::TestOpacityChangeLayerDelegate):
(WTF::TestOpacityChangeLayerDelegate::paintContents):
(WTF::TestOpacityChangeLayerDelegate::drawsContent):
(WTF::TestOpacityChangeLayerDelegate::preserves3D):
(WTF::TestOpacityChangeLayerDelegate::notifySyncRequired):
(WTF::ContentLayerChromiumWithUpdateTracking::create):
(WTF::ContentLayerChromiumWithUpdateTracking::paintContentsCount):
(WTF::ContentLayerChromiumWithUpdateTracking::resetPaintContentsCount):
(WTF::ContentLayerChromiumWithUpdateTracking::updateCount):
(WTF::ContentLayerChromiumWithUpdateTracking::resetUpdateCount):
(WTF::ContentLayerChromiumWithUpdateTracking::paintContentsIfDirty):
(WTF::ContentLayerChromiumWithUpdateTracking::updateCompositorResources):
(WTF::ContentLayerChromiumWithUpdateTracking::ContentLayerChromiumWithUpdateTracking):
(WTF::CCLayerTreeHostTestOpacityChange::CCLayerTreeHostTestOpacityChange):
(WTF::CCLayerTreeHostTestOpacityChange::beginTest):
(WTF::CCLayerTreeHostTestOpacityChange::commitCompleteOnCCThread):
(WTF::CCLayerTreeHostTestOpacityChange::afterTest):
(WTF::TEST_F):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@100702
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2011-11-17 David Reveman <reveman@chromium.org>
+
+ [Chromium] Calls to paintContentsIfDirty() and updateCompositorResources() should be balanced.
+ https://bugs.webkit.org/show_bug.cgi?id=72630
+
+ Reviewed by James Robinson.
+
+ Layer property changes during paintContent() can leave the layer
+ in an invalid state as paintContentsIfDirty() has been called
+ without a matching updateCompositorResources() call. Removing
+ conditionals around these calls ensure they are balanced.
+
+ This patch is tested by the following unit test:
+ - CCLayerTreeHostTestOpacityChange.runMultiThread
+
+ * platform/graphics/chromium/ContentLayerChromium.cpp:
+ (WebCore::ContentLayerChromium::paintContentsIfDirty):
+ * platform/graphics/chromium/VideoLayerChromium.cpp:
+ (WebCore::VideoLayerChromium::updateCompositorResources):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::paintMaskAndReplicaForRenderSurface):
+ (WebCore::CCLayerTreeHost::paintLayerContents):
+ (WebCore::CCLayerTreeHost::updateCompositorResources):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+
2011-11-17 Adam Barth <abarth@webkit.org>
Remove cargo-cult copy/pasting of ScriptExecutionContext namespace
void ContentLayerChromium::paintContentsIfDirty()
{
- ASSERT(drawsContent());
-
updateTileSizeAndTilingOption();
- const IntRect& layerRect = visibleLayerRect();
- if (layerRect.isEmpty())
- return;
+ IntRect layerRect;
+
+ // Always call prepareToUpdate() but with an empty layer rectangle when
+ // layer doesn't draw contents.
+ if (drawsContent())
+ layerRect = visibleLayerRect();
IntRect dirty = enclosingIntRect(m_dirtyRect);
dirty.intersect(IntRect(IntPoint(), contentBounds()));
invalidateRect(dirty);
- if (!drawsContent())
- return;
-
prepareToUpdate(layerRect);
resetNeedsDisplay();
}
void VideoLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
{
- if (!m_delegate || !m_provider)
+ if (!m_delegate || !m_provider || !drawsContent())
return;
if (m_dirtyRect.isEmpty() && texturesValid()) {
return;
}
- ASSERT(drawsContent());
-
m_planes = 0;
m_skipsDraw = false;
paintLayerContents(m_updateList);
}
-static void paintContentsIfDirty(LayerChromium* layer)
-{
- if (layer->drawsContent())
- layer->paintContentsIfDirty();
-}
-
void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer)
{
// Note: Masks and replicas only exist for layers that own render surfaces. If we reach this point
if (renderSurfaceLayer->maskLayer()) {
renderSurfaceLayer->maskLayer()->setLayerTreeHost(this);
renderSurfaceLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), renderSurfaceLayer->contentBounds()));
- paintContentsIfDirty(renderSurfaceLayer->maskLayer());
+ renderSurfaceLayer->maskLayer()->paintContentsIfDirty();
}
LayerChromium* replicaLayer = renderSurfaceLayer->replicaLayer();
if (replicaLayer) {
replicaLayer->setLayerTreeHost(this);
- paintContentsIfDirty(replicaLayer);
+ replicaLayer->paintContentsIfDirty();
if (replicaLayer->maskLayer()) {
replicaLayer->maskLayer()->setLayerTreeHost(this);
replicaLayer->maskLayer()->setVisibleLayerRect(IntRect(IntPoint(), replicaLayer->maskLayer()->contentBounds()));
- paintContentsIfDirty(replicaLayer->maskLayer());
+ replicaLayer->maskLayer()->paintContentsIfDirty();
}
}
}
ASSERT(layer->opacity());
ASSERT(!layer->bounds().isEmpty());
- paintContentsIfDirty(layer);
+ layer->paintContentsIfDirty();
}
}
}
ASSERT(renderSurface->drawOpacity());
if (renderSurfaceLayer->maskLayer())
- updateCompositorResources(renderSurfaceLayer->maskLayer(), context, updater);
+ renderSurfaceLayer->maskLayer()->updateCompositorResources(context, updater);
if (renderSurfaceLayer->replicaLayer()) {
- updateCompositorResources(renderSurfaceLayer->replicaLayer(), context, updater);
+ renderSurfaceLayer->replicaLayer()->updateCompositorResources(context, updater);
if (renderSurfaceLayer->replicaLayer()->maskLayer())
- updateCompositorResources(renderSurfaceLayer->replicaLayer()->maskLayer(), context, updater);
+ renderSurfaceLayer->replicaLayer()->maskLayer()->updateCompositorResources(context, updater);
}
const LayerList& layerList = renderSurface->layerList();
if (layer->renderSurface() && layer->renderSurface() != renderSurface)
continue;
- updateCompositorResources(layer, context, updater);
+ layer->updateCompositorResources(context, updater);
}
}
}
-void CCLayerTreeHost::updateCompositorResources(LayerChromium* layer, GraphicsContext3D* context, CCTextureUpdater& updater)
-{
- // For normal layers, these conditions should have already been checked while creating the render surface layer lists.
- // For masks and replicas however, we may still need to check them here.
- if (layer->bounds().isEmpty() || !layer->opacity() || !layer->drawsContent())
- return;
-
- layer->updateCompositorResources(context, updater);
-}
-
void CCLayerTreeHost::clearPendingUpdate()
{
for (size_t surfaceIndex = 0; surfaceIndex < m_updateList.size(); ++surfaceIndex) {
void paintMaskAndReplicaForRenderSurface(LayerChromium*);
void updateLayers(LayerChromium*);
- void updateCompositorResources(LayerChromium*, GraphicsContext3D*, CCTextureUpdater&);
void clearPendingUpdate();
int m_compositorIdentifier;
+2011-11-17 David Reveman <reveman@chromium.org>
+
+ [Chromium] Calls to paintContentsIfDirty() and updateCompositorResources() should be balanced.
+ https://bugs.webkit.org/show_bug.cgi?id=72630
+
+ Reviewed by James Robinson.
+
+ Add test that check if calls to paintContentsIfDirty() and
+ updateCompositorResources() are balanced when layer opacity
+ changes during paintContent().
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::CCLayerTreeHostTest::layerTreeHost):
+ (WTF::TestOpacityChangeLayerDelegate::TestOpacityChangeLayerDelegate):
+ (WTF::TestOpacityChangeLayerDelegate::paintContents):
+ (WTF::TestOpacityChangeLayerDelegate::drawsContent):
+ (WTF::TestOpacityChangeLayerDelegate::preserves3D):
+ (WTF::TestOpacityChangeLayerDelegate::notifySyncRequired):
+ (WTF::ContentLayerChromiumWithUpdateTracking::create):
+ (WTF::ContentLayerChromiumWithUpdateTracking::paintContentsCount):
+ (WTF::ContentLayerChromiumWithUpdateTracking::resetPaintContentsCount):
+ (WTF::ContentLayerChromiumWithUpdateTracking::updateCount):
+ (WTF::ContentLayerChromiumWithUpdateTracking::resetUpdateCount):
+ (WTF::ContentLayerChromiumWithUpdateTracking::paintContentsIfDirty):
+ (WTF::ContentLayerChromiumWithUpdateTracking::updateCompositorResources):
+ (WTF::ContentLayerChromiumWithUpdateTracking::ContentLayerChromiumWithUpdateTracking):
+ (WTF::CCLayerTreeHostTestOpacityChange::CCLayerTreeHostTestOpacityChange):
+ (WTF::CCLayerTreeHostTestOpacityChange::beginTest):
+ (WTF::CCLayerTreeHostTestOpacityChange::commitCompleteOnCCThread):
+ (WTF::CCLayerTreeHostTestOpacityChange::afterTest):
+ (WTF::TEST_F):
+
2011-11-17 Peter Kasting <pkasting@google.com>
Unreviewed, rolling out r100676.
#include "cc/CCLayerTreeHost.h"
+#include "ContentLayerChromium.h"
#include "cc/CCLayerImpl.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCScopedThreadProxy.h"
+#include "cc/CCTextureUpdater.h"
#include "cc/CCThreadTask.h"
#include "GraphicsContext3DPrivate.h"
#include <gtest/gtest.h>
m_timeoutTask = 0;
}
+ CCLayerTreeHost* layerTreeHost() { return m_layerTreeHost.get(); }
+
protected:
CCLayerTreeHostTest()
runTest(true);
}
+class TestOpacityChangeLayerDelegate : public CCLayerDelegate {
+public:
+ TestOpacityChangeLayerDelegate(CCLayerTreeHostTest* test)
+ : m_test(test)
+ {
+ }
+
+ virtual void paintContents(GraphicsContext&, const IntRect&)
+ {
+ // Set layer opacity to 0.
+ m_test->layerTreeHost()->rootLayer()->setOpacity(0);
+ }
+
+ virtual bool drawsContent() const { return true; }
+ virtual bool preserves3D() { return false; }
+ virtual void notifySyncRequired() { }
+
+private:
+ CCLayerTreeHostTest* m_test;
+};
+
+class ContentLayerChromiumWithUpdateTracking : public ContentLayerChromium {
+public:
+ static PassRefPtr<ContentLayerChromiumWithUpdateTracking> create(CCLayerDelegate *delegate) { return adoptRef(new ContentLayerChromiumWithUpdateTracking(delegate)); }
+
+ int paintContentsCount() { return m_paintContentsCount; }
+ void resetPaintContentsCount() { m_paintContentsCount = 0; }
+
+ int updateCount() { return m_updateCount; }
+ void resetUpdateCount() { m_updateCount = 0; }
+
+ virtual void paintContentsIfDirty()
+ {
+ ContentLayerChromium::paintContentsIfDirty();
+ m_paintContentsCount++;
+ }
+
+ virtual void updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
+ {
+ ContentLayerChromium::updateCompositorResources(context, updater);
+ m_updateCount++;
+ }
+
+private:
+ explicit ContentLayerChromiumWithUpdateTracking(CCLayerDelegate *delegate)
+ : ContentLayerChromium(delegate)
+ , m_paintContentsCount(0)
+ , m_updateCount(0)
+ {
+ setBounds(IntSize(10, 10));
+ }
+
+ int m_paintContentsCount;
+ int m_updateCount;
+};
+
+// Layer opacity change during paint should not prevent compositor resources from being updated during commit.
+class CCLayerTreeHostTestOpacityChange : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestOpacityChange()
+ : m_testOpacityChangeDelegate(this)
+ , m_updateCheckLayer(ContentLayerChromiumWithUpdateTracking::create(&m_testOpacityChangeDelegate))
+ {
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->setRootLayer(m_updateCheckLayer);
+ m_layerTreeHost->setViewport(IntSize(10, 10));
+
+ postSetNeedsCommitToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
+ {
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ // paintContentsIfDirty() should have been called once.
+ EXPECT_EQ(1, m_updateCheckLayer->paintContentsCount());
+
+ // updateCompositorResources() should have been called the same
+ // amout of times as paintContentsIfDirty().
+ EXPECT_EQ(m_updateCheckLayer->paintContentsCount(),
+ m_updateCheckLayer->updateCount());
+ }
+
+private:
+ TestOpacityChangeLayerDelegate m_testOpacityChangeDelegate;
+ RefPtr<ContentLayerChromiumWithUpdateTracking> m_updateCheckLayer;
+};
+
+TEST_F(CCLayerTreeHostTestOpacityChange, runMultiThread)
+{
+ runTest(true);
+}
+
} // namespace