https://bugs.webkit.org/show_bug.cgi?id=80744
Patch by Ian Vollick <vollick@chromium.org> on 2012-03-16
Reviewed by James Robinson.
Source/WebCore:
Tested in CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity
* platform/graphics/chromium/LayerChromium.cpp:
(WebCore::LayerChromium::LayerChromium):
(WebCore::LayerChromium::opacityIsAnimating):
(WebCore):
(WebCore::LayerChromium::transformIsAnimating):
* platform/graphics/chromium/LayerChromium.h:
(LayerChromium):
(WebCore::LayerChromium::drawOpacityIsAnimating):
(WebCore::LayerChromium::setDrawOpacityIsAnimating):
* platform/graphics/chromium/RenderSurfaceChromium.cpp:
(WebCore::RenderSurfaceChromium::RenderSurfaceChromium):
* platform/graphics/chromium/RenderSurfaceChromium.h:
(WebCore::RenderSurfaceChromium::drawOpacityIsAnimating):
(WebCore::RenderSurfaceChromium::setDrawOpacityIsAnimating):
(RenderSurfaceChromium):
* platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
(WebCore::CCLayerAnimationController::isAnimatingProperty):
(WebCore):
* platform/graphics/chromium/cc/CCLayerAnimationController.h:
(CCLayerAnimationController):
* platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp:
(WebCore::CCLayerAnimationControllerImpl::isAnimatingProperty):
(WebCore):
* platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h:
(CCLayerAnimationControllerImpl):
* platform/graphics/chromium/cc/CCLayerImpl.cpp:
(WebCore::CCLayerImpl::CCLayerImpl):
(WebCore::CCLayerImpl::opacityIsAnimating):
(WebCore):
(WebCore::CCLayerImpl::transformIsAnimating):
* platform/graphics/chromium/cc/CCLayerImpl.h:
(CCLayerImpl):
(WebCore::CCLayerImpl::drawOpacityIsAnimating):
(WebCore::CCLayerImpl::setDrawOpacityIsAnimating):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::paintLayerContents):
(WebCore::CCLayerTreeHost::updateCompositorResources):
* platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
(WebCore::layerShouldBeSkipped):
(WebCore::subtreeShouldBeSkipped):
(WebCore):
(WebCore::LayerChromium):
(WebCore::calculateDrawTransformsAndVisibilityInternal):
* platform/graphics/chromium/cc/CCRenderSurface.cpp:
(WebCore::CCRenderSurface::CCRenderSurface):
* platform/graphics/chromium/cc/CCRenderSurface.h:
(WebCore::CCRenderSurface::drawOpacityIsAnimating):
(WebCore::CCRenderSurface::setDrawOpacityIsAnimating):
(CCRenderSurface):
Source/WebKit/chromium:
* tests/CCLayerTreeHostTest.cpp:
(WTF):
(CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity):
(WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity):
(WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::beginTest):
(WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::animateLayers):
(WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::commitCompleteOnCCThread):
(WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::afterTest):
(WTF::TEST_F):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@110980
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-03-16 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Threaded opacity animation jump to opacity of 0
+ https://bugs.webkit.org/show_bug.cgi?id=80744
+
+ Reviewed by James Robinson.
+
+ Tested in CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity
+
+ * platform/graphics/chromium/LayerChromium.cpp:
+ (WebCore::LayerChromium::LayerChromium):
+ (WebCore::LayerChromium::opacityIsAnimating):
+ (WebCore):
+ (WebCore::LayerChromium::transformIsAnimating):
+ * platform/graphics/chromium/LayerChromium.h:
+ (LayerChromium):
+ (WebCore::LayerChromium::drawOpacityIsAnimating):
+ (WebCore::LayerChromium::setDrawOpacityIsAnimating):
+ * platform/graphics/chromium/RenderSurfaceChromium.cpp:
+ (WebCore::RenderSurfaceChromium::RenderSurfaceChromium):
+ * platform/graphics/chromium/RenderSurfaceChromium.h:
+ (WebCore::RenderSurfaceChromium::drawOpacityIsAnimating):
+ (WebCore::RenderSurfaceChromium::setDrawOpacityIsAnimating):
+ (RenderSurfaceChromium):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.cpp:
+ (WebCore::CCLayerAnimationController::isAnimatingProperty):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCLayerAnimationController.h:
+ (CCLayerAnimationController):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp:
+ (WebCore::CCLayerAnimationControllerImpl::isAnimatingProperty):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h:
+ (CCLayerAnimationControllerImpl):
+ * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+ (WebCore::CCLayerImpl::CCLayerImpl):
+ (WebCore::CCLayerImpl::opacityIsAnimating):
+ (WebCore):
+ (WebCore::CCLayerImpl::transformIsAnimating):
+ * platform/graphics/chromium/cc/CCLayerImpl.h:
+ (CCLayerImpl):
+ (WebCore::CCLayerImpl::drawOpacityIsAnimating):
+ (WebCore::CCLayerImpl::setDrawOpacityIsAnimating):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::paintLayerContents):
+ (WebCore::CCLayerTreeHost::updateCompositorResources):
+ * platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
+ (WebCore::layerShouldBeSkipped):
+ (WebCore::subtreeShouldBeSkipped):
+ (WebCore):
+ (WebCore::LayerChromium):
+ (WebCore::calculateDrawTransformsAndVisibilityInternal):
+ * platform/graphics/chromium/cc/CCRenderSurface.cpp:
+ (WebCore::CCRenderSurface::CCRenderSurface):
+ * platform/graphics/chromium/cc/CCRenderSurface.h:
+ (WebCore::CCRenderSurface::drawOpacityIsAnimating):
+ (WebCore::CCRenderSurface::setDrawOpacityIsAnimating):
+ (CCRenderSurface):
+
2012-03-15 Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
[TexMap] Reuse textures following the same rules as they do internally.
, m_alwaysReserveTextures(false)
, m_replicaLayer(0)
, m_drawOpacity(0)
+ , m_drawOpacityIsAnimating(false)
, m_targetRenderSurface(0)
, m_contentsScale(1.0)
, m_layerAnimationDelegate(0)
setNeedsCommit();
}
+bool LayerChromium::opacityIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity);
+}
+
void LayerChromium::setOpaque(bool opaque)
{
if (m_opaque == opaque)
setNeedsCommit();
}
+bool LayerChromium::transformIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform);
+}
+
void LayerChromium::setScrollPosition(const IntPoint& scrollPosition)
{
if (m_scrollPosition == scrollPosition)
void setOpacity(float);
float opacity() const { return m_opacity; }
+ bool opacityIsAnimating() const;
void setFilters(const FilterOperations&);
const FilterOperations& filters() const { return m_filters; }
void setTransform(const TransformationMatrix&);
const TransformationMatrix& transform() const { return m_transform; }
+ bool transformIsAnimating() const;
const IntRect& visibleLayerRect() const { return m_visibleLayerRect; }
void setVisibleLayerRect(const IntRect& visibleLayerRect) { m_visibleLayerRect = visibleLayerRect; }
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
RenderSurfaceChromium* targetRenderSurface() const { return m_targetRenderSurface; }
// Transient properties.
OwnPtr<RenderSurfaceChromium> m_renderSurface;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
IntRect m_clipRect;
RenderSurfaceChromium* m_targetRenderSurface;
TransformationMatrix m_drawTransform;
, m_maskLayer(0)
, m_skipsDraw(false)
, m_drawOpacity(1)
+ , m_drawOpacityIsAnimating(false)
, m_nearestAncestorThatMovesPixels(0)
{
}
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float drawOpacity) { m_drawOpacity = drawOpacity; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
// This goes from content space with the origin in the center of the rect being transformed to the target space with the origin in the top left of the
// rect being transformed. Position the rect so that the origin is in the center of it before applying this transform.
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
bool m_skipsDraw;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
TransformationMatrix m_drawTransform;
TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
return 0;
}
+bool CCLayerAnimationController::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return true;
+ }
+ return false;
+}
+
void CCLayerAnimationController::remove(int groupId, CCActiveAnimation::TargetProperty targetProperty)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
bool hasActiveAnimation() const { return m_activeAnimations.size(); }
CCActiveAnimation* getActiveAnimation(int groupId, CCActiveAnimation::TargetProperty);
+ bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
protected:
CCLayerAnimationController();
return false;
}
+bool CCLayerAnimationControllerImpl::isAnimatingProperty(CCActiveAnimation::TargetProperty targetProperty) const
+{
+ for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
+ if (m_activeAnimations[i]->runState() != CCActiveAnimation::Finished && m_activeAnimations[i]->runState() != CCActiveAnimation::Aborted && m_activeAnimations[i]->targetProperty() == targetProperty)
+ return true;
+ }
+ return false;
+}
+
void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector& events)
{
for (size_t i = 0; i < m_activeAnimations.size(); ++i) {
// Returns true if there are any animations that are neither finished nor aborted.
bool hasActiveAnimation() const;
+ bool isAnimatingProperty(CCActiveAnimation::TargetProperty) const;
+
private:
friend class CCLayerAnimationController;
, m_targetRenderSurface(0)
, m_drawDepth(0)
, m_drawOpacity(0)
+ , m_drawOpacityIsAnimating(false)
, m_debugBorderColor(0, 0, 0, 0)
, m_debugBorderWidth(0)
, m_layerAnimationController(CCLayerAnimationControllerImpl::create(this))
noteLayerPropertyChangedForSubtree();
}
+bool CCLayerImpl::opacityIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Opacity);
+}
+
void CCLayerImpl::setPosition(const FloatPoint& position)
{
if (m_position == position)
noteLayerPropertyChangedForSubtree();
}
+bool CCLayerImpl::transformIsAnimating() const
+{
+ return m_layerAnimationController->isAnimatingProperty(CCActiveAnimation::Transform);
+}
+
void CCLayerImpl::setDebugBorderColor(Color debugBorderColor)
{
if (m_debugBorderColor == debugBorderColor)
// CCLayerAnimationControllerImplClient implementation.
virtual int id() const { return m_layerId; }
+
virtual void setOpacity(float);
virtual float opacity() const { return m_opacity; }
+ bool opacityIsAnimating() const;
+
virtual void setTransform(const TransformationMatrix&);
virtual const TransformationMatrix& transform() const { return m_transform; }
+ bool transformIsAnimating() const;
+
virtual const IntSize& bounds() const { return m_bounds; }
virtual ~CCLayerImpl();
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
const IntRect& clipRect() const { return m_clipRect; }
void setClipRect(const IntRect& rect) { m_clipRect = rect; }
CCRenderSurface* targetRenderSurface() const { return m_targetRenderSurface; }
// to sort layers from back to front.
float m_drawDepth;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
// Debug borders.
Color m_debugBorderColor;
CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) {
if (it.representsTargetRenderSurface()) {
- ASSERT(it->renderSurface()->drawOpacity());
+ ASSERT(it->renderSurface()->drawOpacity() || it->drawOpacityIsAnimating());
occlusionTracker.finishedTargetRenderSurface(*it, it->renderSurface());
paintMaskAndReplicaForRenderSurface(*it, paintType);
CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList);
for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) {
if (it.representsTargetRenderSurface()) {
- ASSERT(it->renderSurface()->drawOpacity());
+ ASSERT(it->renderSurface()->drawOpacity() || it->drawOpacityIsAnimating());
if (it->maskLayer())
it->maskLayer()->updateCompositorResources(context, updater);
// Some additional conditions need to be computed at a later point after the recursion is finished.
// - the intersection of render surface content and layer clipRect is empty
// - the visibleLayerRect is empty
+ //
+ // Note, if the layer should not have been drawn due to being fully transparent,
+ // we would have skipped the entire subtree and never made it into this function,
+ // so it is safe to omit this check here.
- if (!layer->drawsContent() || !layer->opacity() || layer->bounds().isEmpty())
+ if (!layer->drawsContent() || layer->bounds().isEmpty())
return true;
// The layer should not be drawn if (1) it is not double-sided and (2) the back of the layer is facing the screen.
return false;
}
+static bool subtreeShouldBeSkipped(CCLayerImpl* layer)
+{
+ // The opacity of a layer always applies to its children (either implicitly
+ // via a render surface or explicitly if the parent preserves 3D), so the
+ // entire subtree can be skipped if this layer is fully transparent.
+ return !layer->opacity();
+}
+
+static bool subtreeShouldBeSkipped(LayerChromium* layer)
+{
+ // If the opacity is being animated then the opacity on the main thread is unreliable
+ // (since the impl thread may be using a different opacity), so it should not be trusted.
+ // In particular, it should not cause the subtree to be skipped.
+ return !layer->opacity() && !layer->opacityIsAnimating();
+}
+
template<typename LayerType>
static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlignedWithRespectToParent)
{
// S is the scale adjustment (to scale up to the layer size)
//
+ if (subtreeShouldBeSkipped(layer))
+ return false;
+
float drawOpacity = layer->opacity();
- if (layer->parent() && layer->parent()->preserves3D())
+ bool drawOpacityIsAnimating = layer->opacityIsAnimating();
+ if (layer->parent() && layer->parent()->preserves3D()) {
drawOpacity *= layer->parent()->drawOpacity();
- // The opacity of a layer always applies to its children (either implicitly
- // via a render surface or explicitly if the parent preserves 3D), so the
- // entire subtree can be skipped if this layer is fully transparent.
- if (!drawOpacity)
- return false;
+ drawOpacityIsAnimating |= layer->parent()->drawOpacityIsAnimating();
+ }
IntSize bounds = layer->bounds();
FloatPoint anchorPoint = layer->anchorPoint();
// The opacity value is moved from the layer to its surface, so that the entire subtree properly inherits opacity.
renderSurface->setDrawOpacity(drawOpacity);
+ renderSurface->setDrawOpacityIsAnimating(drawOpacityIsAnimating);
layer->setDrawOpacity(1);
+ layer->setDrawOpacityIsAnimating(false);
TransformationMatrix layerOriginTransform = combinedTransform;
layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
transformedLayerRect = enclosingIntRect(layer->drawTransform().mapRect(layerRect));
layer->setDrawOpacity(drawOpacity);
+ layer->setDrawOpacityIsAnimating(drawOpacityIsAnimating);
if (layer != rootLayer) {
ASSERT(layer->parent());
, m_skipsDraw(false)
, m_surfacePropertyChanged(false)
, m_drawOpacity(1)
+ , m_drawOpacityIsAnimating(false)
, m_nearestAncestorThatMovesPixels(0)
{
m_damageTracker = CCDamageTracker::create();
float drawOpacity() const { return m_drawOpacity; }
void setDrawOpacity(float opacity) { m_drawOpacity = opacity; }
+ bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
+ void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
+
void setDrawTransform(const TransformationMatrix& drawTransform) { m_drawTransform = drawTransform; }
const TransformationMatrix& drawTransform() const { return m_drawTransform; }
OwnPtr<ManagedTexture> m_contentsTexture;
float m_drawOpacity;
+ bool m_drawOpacityIsAnimating;
TransformationMatrix m_drawTransform;
TransformationMatrix m_replicaDrawTransform;
TransformationMatrix m_originTransform;
+2012-03-16 Ian Vollick <vollick@chromium.org>
+
+ [chromium] Threaded opacity animation jump to opacity of 0
+ https://bugs.webkit.org/show_bug.cgi?id=80744
+
+ Reviewed by James Robinson.
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF):
+ (CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity):
+ (WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity):
+ (WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::beginTest):
+ (WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::animateLayers):
+ (WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::commitCompleteOnCCThread):
+ (WTF::CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity::afterTest):
+ (WTF::TEST_F):
+
2012-03-16 Dana Jansens <danakj@chromium.org>
[chromium] Changes to overdraw metrics to allow upload tracking
CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
ASSERT(test);
if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
- addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 1);
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 0, 0, 0.5);
}
static void dispatchAddAnimation(void* self)
CCLayerTreeHostTest* test = static_cast<CCLayerTreeHostTest*>(self);
ASSERT(test);
if (test->m_layerTreeHost && test->m_layerTreeHost->rootLayer())
- addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 1);
+ addOpacityTransitionToLayer(*test->m_layerTreeHost->rootLayer(), 10, 0, 0.5);
}
static void dispatchSetNeedsAnimateAndCommit(void* self)
runTestThreaded();
}
+// Ensures that when opacity is being animated, this value does not cause the subtree to be skipped.
+class CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity : public CCLayerTreeHostTestThreadOnly {
+public:
+ CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity()
+ {
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->rootLayer()->setDrawOpacity(1);
+ m_layerTreeHost->setViewportSize(IntSize(10, 10));
+ m_layerTreeHost->rootLayer()->setOpacity(0);
+ postAddAnimationToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl*)
+ {
+ // If the subtree was skipped when preparing to draw, the layer's draw opacity
+ // will not have been updated. It should be set to 0 due to the animation.
+ // Without the animation, the layer will be skipped since it has zero opacity.
+ EXPECT_EQ(0, m_layerTreeHost->rootLayer()->drawOpacity());
+ endTest();
+ }
+
+ virtual void afterTest()
+ {
+ }
+};
+
+TEST_F(CCLayerTreeHostTestDoNotSkipLayersWithAnimatedOpacity, runMultiThread)
+{
+ runTestThreaded();
+}
+
class CCLayerTreeHostTestScrollSimple : public CCLayerTreeHostTestThreadOnly {
public:
CCLayerTreeHostTestScrollSimple()