Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / compositing / CompositingReasonFinder.cpp
index 261c935..6f6ce3d 100644 (file)
@@ -5,52 +5,43 @@
 #include "config.h"
 #include "core/rendering/compositing/CompositingReasonFinder.h"
 
-#include "CSSPropertyNames.h"
-#include "HTMLNames.h"
-#include "core/animation/ActiveAnimations.h"
+#include "core/CSSPropertyNames.h"
+#include "core/dom/Document.h"
 #include "core/frame/FrameView.h"
-#include "core/frame/LocalFrame.h"
 #include "core/frame/Settings.h"
-#include "core/html/HTMLCanvasElement.h"
-#include "core/html/HTMLIFrameElement.h"
-#include "core/html/HTMLMediaElement.h"
-#include "core/html/canvas/CanvasRenderingContext.h"
-#include "core/page/Chrome.h"
 #include "core/page/Page.h"
-#include "core/rendering/RenderApplet.h"
-#include "core/rendering/RenderEmbeddedObject.h"
-#include "core/rendering/RenderFullScreen.h"
-#include "core/rendering/RenderGeometryMap.h"
-#include "core/rendering/RenderIFrame.h"
-#include "core/rendering/RenderLayer.h"
-#include "core/rendering/RenderLayerStackingNode.h"
-#include "core/rendering/RenderLayerStackingNodeIterator.h"
-#include "core/rendering/RenderReplica.h"
-#include "core/rendering/RenderVideo.h"
 #include "core/rendering/RenderView.h"
 #include "core/rendering/compositing/RenderLayerCompositor.h"
 
-namespace WebCore {
+namespace blink {
 
 CompositingReasonFinder::CompositingReasonFinder(RenderView& renderView)
     : m_renderView(renderView)
     , m_compositingTriggers(static_cast<CompositingTriggerFlags>(AllCompositingTriggers))
 {
+    updateTriggers();
 }
 
 void CompositingReasonFinder::updateTriggers()
 {
-    m_compositingTriggers = m_renderView.document().page()->chrome().client().allowedCompositingTriggers();
-}
+    m_compositingTriggers = 0;
 
-bool CompositingReasonFinder::has3DTransformTrigger() const
-{
-    return m_compositingTriggers & ThreeDTransformTrigger;
+    Settings& settings = m_renderView.document().page()->settings();
+    if (settings.compositedScrollingForFramesEnabled())
+        m_compositingTriggers |= ScrollableInnerFrameTrigger;
+
+    // We map both these settings to universal overlow scrolling.
+    // FIXME: Replace these settings with a generic compositing setting for HighDPI.
+    if (settings.acceleratedCompositingForOverflowScrollEnabled() || settings.compositorDrivenAcceleratedScrollingEnabled())
+        m_compositingTriggers |= OverflowScrollTrigger;
+
+    if (settings.acceleratedCompositingForFixedPositionEnabled())
+        m_compositingTriggers |= ViewportConstrainedPositionedTrigger;
 }
 
-bool CompositingReasonFinder::hasAnimationTrigger() const
+bool CompositingReasonFinder::hasOverflowScrollTrigger() const
 {
-    return m_compositingTriggers & AnimationTrigger;
+    return m_compositingTriggers & OverflowScrollTrigger;
 }
 
 bool CompositingReasonFinder::isMainFrame() const
@@ -59,11 +50,11 @@ bool CompositingReasonFinder::isMainFrame() const
     return !m_renderView.document().ownerElement();
 }
 
-CompositingReasons CompositingReasonFinder::directReasons(const RenderLayer* layer, bool* needToRecomputeCompositingRequirements) const
+CompositingReasons CompositingReasonFinder::directReasons(const RenderLayer* layer) const
 {
-    CompositingReasons styleReasons = layer->styleDeterminedCompositingReasons();
-    ASSERT(styleDeterminedReasons(layer->renderer()) == styleReasons);
-    return styleReasons | nonStyleDeterminedDirectReasons(layer, needToRecomputeCompositingRequirements);
+    ASSERT(potentialCompositingReasonsFromStyle(layer->renderer()) == layer->potentialCompositingReasonsFromStyle());
+    CompositingReasons styleDeterminedDirectCompositingReasons = layer->potentialCompositingReasonsFromStyle() & CompositingReasonComboAllDirectStyleDeterminedReasons;
+    return styleDeterminedDirectCompositingReasons | nonStyleDeterminedDirectReasons(layer);
 }
 
 // This information doesn't appear to be incorporated into CompositingReasons.
@@ -77,236 +68,111 @@ bool CompositingReasonFinder::requiresCompositingForScrollableFrame() const
     if (!(m_compositingTriggers & ScrollableInnerFrameTrigger))
         return false;
 
-    FrameView* frameView = m_renderView.frameView();
-    return frameView->isScrollable();
+    return m_renderView.frameView()->isScrollable();
 }
 
-CompositingReasons CompositingReasonFinder::styleDeterminedReasons(RenderObject* renderer) const
+CompositingReasons CompositingReasonFinder::potentialCompositingReasonsFromStyle(RenderObject* renderer) const
 {
-    CompositingReasons directReasons = CompositingReasonNone;
+    CompositingReasons reasons = CompositingReasonNone;
+
+    RenderStyle* style = renderer->style();
 
     if (requiresCompositingForTransform(renderer))
-        directReasons |= CompositingReason3DTransform;
+        reasons |= CompositingReason3DTransform;
 
-    if (requiresCompositingForBackfaceVisibilityHidden(renderer))
-        directReasons |= CompositingReasonBackfaceVisibilityHidden;
+    if (style->backfaceVisibility() == BackfaceVisibilityHidden)
+        reasons |= CompositingReasonBackfaceVisibilityHidden;
 
-    if (requiresCompositingForFilters(renderer))
-        directReasons |= CompositingReasonFilters;
+    if (requiresCompositingForAnimation(style))
+        reasons |= CompositingReasonActiveAnimation;
 
-    if (requiresCompositingForWillChange(renderer))
-        directReasons |= CompositingReasonWillChange;
+    if (style->hasWillChangeCompositingHint() && !style->subtreeWillChangeContents())
+        reasons |= CompositingReasonWillChangeCompositingHint;
 
-    ASSERT(!(directReasons & ~CompositingReasonComboAllStyleDeterminedReasons));
-    return directReasons;
-}
+    if (style->hasInlineTransform())
+        reasons |= CompositingReasonInlineTransform;
 
-bool CompositingReasonFinder::requiresCompositingForTransform(RenderObject* renderer) const
-{
-    if (!(m_compositingTriggers & ThreeDTransformTrigger))
-        return false;
+    if (style->transformStyle3D() == TransformStyle3DPreserve3D)
+        reasons |= CompositingReasonPreserve3DWith3DDescendants;
 
-    // Note that we ask the renderer if it has a transform, because the style may have transforms,
-    // but the renderer may be an inline that doesn't suppport them.
-    return renderer->hasTransform() && renderer->style()->transform().has3DOperation();
-}
+    if (style->hasPerspective())
+        reasons |= CompositingReasonPerspectiveWith3DDescendants;
 
-bool CompositingReasonFinder::requiresCompositingForBackfaceVisibilityHidden(RenderObject* renderer) const
-{
-    if (!(m_compositingTriggers & ThreeDTransformTrigger))
-        return false;
+    // If the implementation of createsGroup changes, we need to be aware of that in this part of code.
+    ASSERT((renderer->isTransparent() || renderer->hasMask() || renderer->hasFilter() || renderer->hasBlendMode()) == renderer->createsGroup());
 
-    return renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden;
-}
+    if (style->hasMask())
+        reasons |= CompositingReasonMaskWithCompositedDescendants;
 
-bool CompositingReasonFinder::requiresCompositingForFilters(RenderObject* renderer) const
-{
-    if (!(m_compositingTriggers & FilterTrigger))
-        return false;
+    if (style->hasFilter())
+        reasons |= CompositingReasonFilterWithCompositedDescendants;
 
-    return renderer->hasFilter();
-}
+    // See RenderLayer::updateTransform for an explanation of why we check both.
+    if (renderer->hasTransform() && style->hasTransform())
+        reasons |= CompositingReasonTransformWithCompositedDescendants;
 
-bool CompositingReasonFinder::requiresCompositingForWillChange(const RenderObject* renderer) const
-{
-    if (renderer->style()->hasWillChangeCompositingHint())
-        return true;
+    if (renderer->isTransparent())
+        reasons |= CompositingReasonOpacityWithCompositedDescendants;
 
-    if (!(m_compositingTriggers & GPURasterizationTrigger))
-        return false;
+    if (renderer->hasBlendMode())
+        reasons |= CompositingReasonBlendingWithCompositedDescendants;
+
+    if (renderer->hasReflection())
+        reasons |= CompositingReasonReflectionWithCompositedDescendants;
+
+    ASSERT(!(reasons & ~CompositingReasonComboAllStyleDeterminedReasons));
+    return reasons;
+}
 
-    return renderer->style()->hasWillChangeGpuRasterizationHint();
+bool CompositingReasonFinder::requiresCompositingForTransform(RenderObject* renderer) const
+{
+    // Note that we ask the renderer if it has a transform, because the style may have transforms,
+    // but the renderer may be an inline that doesn't suppport them.
+    return renderer->hasTransform() && renderer->style()->transform().has3DOperation();
 }
 
-CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(const RenderLayer* layer, bool* needToRecomputeCompositingRequirements) const
+CompositingReasons CompositingReasonFinder::nonStyleDeterminedDirectReasons(const RenderLayer* layer) const
 {
     CompositingReasons directReasons = CompositingReasonNone;
     RenderObject* renderer = layer->renderer();
 
-    if (requiresCompositingForAnimation(renderer))
-        directReasons |= CompositingReasonActiveAnimation;
-
-    if (m_renderView.compositorDrivenAcceleratedScrollingEnabled()) {
-        if (requiresCompositingForOutOfFlowClipping(layer))
+    if (hasOverflowScrollTrigger()) {
+        if (layer->clipParent())
             directReasons |= CompositingReasonOutOfFlowClipping;
 
-        if (requiresCompositingForOverflowScrollingParent(layer))
-            directReasons |= CompositingReasonOverflowScrollingParent;
-    }
+        if (const RenderLayer* scrollingAncestor = layer->ancestorScrollingLayer()) {
+            if (scrollingAncestor->needsCompositedScrolling() && layer->scrollParent())
+                directReasons |= CompositingReasonOverflowScrollingParent;
+        }
 
-    if (requiresCompositingForOverflowScrolling(layer))
-        directReasons |= CompositingReasonOverflowScrollingTouch;
+        if (layer->needsCompositedScrolling())
+            directReasons |= CompositingReasonOverflowScrollingTouch;
+    }
 
-    if (requiresCompositingForPosition(renderer, layer, 0, needToRecomputeCompositingRequirements))
-        directReasons |= renderer->style()->position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
+    if (requiresCompositingForPositionFixed(layer))
+        directReasons |= CompositingReasonPositionFixed;
 
-    directReasons |= renderer->additionalCompositingReasons(m_compositingTriggers);
+    directReasons |= renderer->additionalCompositingReasons();
 
     ASSERT(!(directReasons & CompositingReasonComboAllStyleDeterminedReasons));
     return directReasons;
 }
 
-bool CompositingReasonFinder::requiresCompositingForAnimation(RenderObject* renderer) const
-{
-    if (!(m_compositingTriggers & AnimationTrigger))
-        return false;
-
-    return shouldCompositeForActiveAnimations(*renderer);
-}
-
-bool CompositingReasonFinder::requiresCompositingForOutOfFlowClipping(const RenderLayer* layer) const
+bool CompositingReasonFinder::requiresCompositingForAnimation(RenderStyle* style) const
 {
-    return layer->isUnclippedDescendant();
-}
-
-bool CompositingReasonFinder::requiresCompositingForOverflowScrollingParent(const RenderLayer* layer) const
-{
-    return layer->scrollParent();
-}
-
-bool CompositingReasonFinder::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
-{
-    return layer->needsCompositedScrolling();
-}
-
-bool CompositingReasonFinder::isViewportConstrainedFixedOrStickyLayer(const RenderLayer* layer)
-{
-    if (layer->renderer()->isStickyPositioned())
-        return !layer->enclosingOverflowClipLayer(ExcludeSelf);
-
-    if (layer->renderer()->style()->position() != FixedPosition)
-        return false;
-
-    for (const RenderLayerStackingNode* stackingContainer = layer->stackingNode(); stackingContainer;
-        stackingContainer = stackingContainer->ancestorStackingContainerNode()) {
-        if (stackingContainer->layer()->compositingState() != NotComposited
-            && stackingContainer->layer()->renderer()->style()->position() == FixedPosition)
-            return false;
-    }
+    if (style->subtreeWillChangeContents())
+        return style->isRunningAnimationOnCompositor();
 
-    return true;
+    return style->shouldCompositeForCurrentAnimations();
 }
 
-bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const
+bool CompositingReasonFinder::requiresCompositingForPositionFixed(const RenderLayer* layer) const
 {
-    // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
-    // opacity, transform) can get their own composited layer. A stacking context is required otherwise
-    // z-index and clipping will be broken.
-    if (!renderer->isPositioned())
-        return false;
-
-    EPosition position = renderer->style()->position();
-    bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition;
-    // FIXME: The isStackingContainer check here is redundant. Fixed position elements are always stacking contexts.
-    if (isFixed && !layer->stackingNode()->isStackingContainer())
-        return false;
-
-    bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition;
-    if (!isFixed && !isSticky)
-        return false;
-
-    // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
-    if (Settings* settings = m_renderView.document().settings()) {
-        if (!settings->acceleratedCompositingForFixedPositionEnabled())
-            return false;
-    }
-
-    if (isSticky)
-        return isViewportConstrainedFixedOrStickyLayer(layer);
-
-    RenderObject* container = renderer->container();
-    // If the renderer is not hooked up yet then we have to wait until it is.
-    if (!container) {
-        *needToRecomputeCompositingRequirements = true;
+    if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger))
         return false;
-    }
-
     // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
     // They will stay fixed wrt the container rather than the enclosing frame.
-    if (container != &m_renderView) {
-        if (viewportConstrainedNotCompositedReason)
-            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer;
-        return false;
-    }
-
-    // If the fixed-position element does not have any scrollable ancestor between it and
-    // its container, then we do not need to spend compositor resources for it. Start by
-    // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below.
-    bool hasScrollableAncestor = false;
-
-    // The FrameView has the scrollbars associated with the top level viewport, so we have to
-    // check the FrameView in addition to the hierarchy of ancestors.
-    FrameView* frameView = m_renderView.frameView();
-    if (frameView && frameView->isScrollable())
-        hasScrollableAncestor = true;
-
-    RenderLayer* ancestor = layer->parent();
-    while (ancestor && !hasScrollableAncestor) {
-        if (frameView->containsScrollableArea(ancestor->scrollableArea()))
-            hasScrollableAncestor = true;
-        if (ancestor->renderer() == &m_renderView)
-            break;
-        ancestor = ancestor->parent();
-    }
-
-    if (!hasScrollableAncestor) {
-        if (viewportConstrainedNotCompositedReason)
-            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors;
-        return false;
-    }
-
-    // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done.
-    if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) {
-        *needToRecomputeCompositingRequirements = true;
-        return layer->hasCompositedLayerMapping();
-    }
-
-    bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
-    if (!paintsContent) {
-        if (viewportConstrainedNotCompositedReason)
-            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent;
-        return false;
-    }
-
-    // Fixed position elements that are invisible in the current view don't get their own layer.
-    if (FrameView* frameView = m_renderView.frameView()) {
-        LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect();
-        LayoutRect layerBounds = layer->calculateLayerBounds(layer->compositor()->rootRenderLayer(), 0,
-            RenderLayer::DefaultCalculateLayerBoundsFlags
-            | RenderLayer::ExcludeHiddenDescendants
-            | RenderLayer::DontConstrainForMask
-            | RenderLayer::IncludeCompositedDescendants
-            | RenderLayer::PretendLayerHasOwnBacking);
-        if (!viewBounds.intersects(enclosingIntRect(layerBounds))) {
-            if (viewportConstrainedNotCompositedReason) {
-                *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
-                *needToRecomputeCompositingRequirements = true;
-            }
-            return false;
-        }
-    }
-
-    return true;
+    return layer->scrollsWithViewport() && m_renderView.frameView()->isScrollable();
 }
 
 }