| Index: third_party/WebKit/Source/core/paint/PaintLayer.h | 
| diff --git a/third_party/WebKit/Source/core/paint/PaintLayer.h b/third_party/WebKit/Source/core/paint/PaintLayer.h | 
| index 073009e9d4aa0b1c2290f624a524def54f5fec5c..dd5f4f5142708bd1199a8da0aaab94d59007832c 100644 | 
| --- a/third_party/WebKit/Source/core/paint/PaintLayer.h | 
| +++ b/third_party/WebKit/Source/core/paint/PaintLayer.h | 
| @@ -90,6 +90,49 @@ private: | 
| TemporaryChange<CompositingQueryMode> m_disabler; | 
| }; | 
|  | 
| +struct PaintLayerRareData { | 
| +    PaintLayerRareData(); | 
| +    ~PaintLayerRareData(); | 
| + | 
| +    // Our current relative position offset. | 
| +    LayoutSize offsetForInFlowPosition; | 
| + | 
| +    OwnPtr<TransformationMatrix> transform; | 
| + | 
| +    // Pointer to the enclosing Layer that caused us to be paginated. It is 0 if we are not paginated. | 
| +    // | 
| +    // See LayoutMultiColumnFlowThread and | 
| +    // https://sites.google.com/a/chromium.org/dev/developers/design-documents/multi-column-layout | 
| +    // for more information about the multicol implementation. It's important to understand the | 
| +    // difference between flow thread coordinates and visual coordinates when working with multicol | 
| +    // in Layer, since Layer is one of the few places where we have to worry about the | 
| +    // visual ones. Internally we try to use flow-thread coordinates whenever possible. | 
| +    PaintLayer* enclosingPaginationLayer; | 
| + | 
| +    // These compositing reasons are updated whenever style changes, not while updating compositing layers. | 
| +    // They should not be used to infer the compositing state of this layer. | 
| +    CompositingReasons potentialCompositingReasonsFromStyle; | 
| + | 
| +    // Once computed, indicates all that a layer needs to become composited using the CompositingReasons enum bitfield. | 
| +    CompositingReasons compositingReasons; | 
| + | 
| +    // If the layer paints into its own backings, this keeps track of the backings. | 
| +    // It's nullptr if the layer is not composited or paints into grouped backing. | 
| +    OwnPtr<CompositedLayerMapping> compositedLayerMapping; | 
| + | 
| +    // If the layer paints into grouped backing (i.e. squashed), this points to the | 
| +    // grouped CompositedLayerMapping. It's null if the layer is not composited or | 
| +    // paints into its own backing. | 
| +    CompositedLayerMapping* groupedMapping; | 
| + | 
| +    IntRect blockSelectionGapsBounds; | 
| + | 
| +    OwnPtr<PaintLayerReflectionInfo> reflectionInfo; | 
| + | 
| +    // The accumulated subpixel offset of a composited layer's composited bounds compared to absolute coordinates. | 
| +    LayoutSize subpixelAccumulation; | 
| +}; | 
| + | 
| // PaintLayer is an old object that handles lots of unrelated operations. | 
| // | 
| // We want it to die at some point and be replaced by more focused objects, | 
| @@ -161,11 +204,11 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient { | 
| WTF_MAKE_NONCOPYABLE(PaintLayer); | 
| public: | 
| PaintLayer(LayoutBoxModelObject*, PaintLayerType); | 
| -    ~PaintLayer(); | 
| +    ~PaintLayer() override; | 
|  | 
| // DisplayItemClient methods | 
| String debugName() const final; | 
| -    IntRect visualRect() const override; | 
| +    IntRect visualRect() const final; | 
|  | 
| LayoutBoxModelObject* layoutObject() const { return m_layoutObject; } | 
| LayoutBox* layoutBox() const { return m_layoutObject && m_layoutObject->isBox() ? toLayoutBox(m_layoutObject) : 0; } | 
| @@ -190,13 +233,13 @@ public: | 
| // FIXME: Many people call this function while it has out-of-date information. | 
| bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; } | 
|  | 
| -    void setLayerType(PaintLayerType layerType) { m_layerType = layerType; } | 
| +    void setLayerType(PaintLayerType layerType) { m_layerType = layerType; ASSERT(static_cast<PaintLayerType>(m_layerType) == layerType); } | 
|  | 
| bool isTransparent() const { return layoutObject()->isTransparent() || layoutObject()->style()->hasBlendMode() || layoutObject()->hasMask(); } | 
|  | 
| bool isReflection() const { return layoutObject()->isReplica(); } | 
| -    PaintLayerReflectionInfo* reflectionInfo() { return m_reflectionInfo.get(); } | 
| -    const PaintLayerReflectionInfo* reflectionInfo() const { return m_reflectionInfo.get(); } | 
| +    PaintLayerReflectionInfo* reflectionInfo() { return m_rareData ? m_rareData->reflectionInfo.get() : nullptr; } | 
| +    const PaintLayerReflectionInfo* reflectionInfo() const { return const_cast<PaintLayer*>(this)->reflectionInfo(); } | 
|  | 
| const PaintLayer* root() const | 
| { | 
| @@ -225,12 +268,12 @@ public: | 
| void updateLayerPositionsAfterLayout(); | 
| void updateLayerPositionsAfterOverflowScroll(const DoubleSize& scrollDelta); | 
|  | 
| -    PaintLayer* enclosingPaginationLayer() const { return m_enclosingPaginationLayer; } | 
| +    PaintLayer* enclosingPaginationLayer() const { return m_rareData ? m_rareData->enclosingPaginationLayer : nullptr; } | 
|  | 
| void updateTransformationMatrix(); | 
| PaintLayer* renderingContextRoot(); | 
|  | 
| -    const LayoutSize& offsetForInFlowPosition() const { return m_offsetForInFlowPosition; } | 
| +    LayoutSize offsetForInFlowPosition() const { return m_rareData ? m_rareData->offsetForInFlowPosition : LayoutSize(); } | 
|  | 
| void addBlockSelectionGapsBounds(const LayoutRect&); | 
| void clearBlockSelectionGapsBounds(); | 
| @@ -341,9 +384,7 @@ public: | 
|  | 
| bool hasTransformRelatedProperty() const { return layoutObject()->hasTransformRelatedProperty(); } | 
| // Note that this transform has the transform-origin baked in. | 
| -    TransformationMatrix* transform() const { return m_transform.get(); } | 
| -    void setTransform(PassOwnPtr<TransformationMatrix> transform) { m_transform = transform; } | 
| -    void clearTransform() { m_transform.clear(); } | 
| +    TransformationMatrix* transform() const { return m_rareData ? m_rareData->transform.get() : nullptr; } | 
|  | 
| // currentTransform computes a transform which takes accelerated animations into account. The | 
| // resulting transform has transform-origin baked in. If the layer does not have a transform, | 
| @@ -357,7 +398,7 @@ public: | 
| TransformationMatrix perspectiveTransform() const; | 
| FloatPoint perspectiveOrigin() const; | 
| bool preserves3D() const { return layoutObject()->style()->transformStyle3D() == TransformStyle3DPreserve3D; } | 
| -    bool has3DTransform() const { return m_transform && !m_transform->isAffine(); } | 
| +    bool has3DTransform() const { return m_rareData && m_rareData->transform && !m_rareData->transform->isAffine(); } | 
|  | 
| // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959 | 
| bool shouldPreserve3D() const { return !layoutObject()->hasReflection() && layoutObject()->style()->transformStyle3D() == TransformStyle3DPreserve3D; } | 
| @@ -384,10 +425,10 @@ public: | 
| // (and not just to do bookkeeping related to the mapping like, say, allocating or deallocating a mapping), | 
| // then you may have incorrect logic. Use compositingState() instead. | 
| // FIXME: This is identical to null checking compositedLayerMapping(), why not just call that? | 
| -    bool hasCompositedLayerMapping() const { return m_compositedLayerMapping.get(); } | 
| +    bool hasCompositedLayerMapping() const { return m_rareData && m_rareData->compositedLayerMapping; } | 
| void ensureCompositedLayerMapping(); | 
| void clearCompositedLayerMapping(bool layerBeingDestroyed = false); | 
| -    CompositedLayerMapping* groupedMapping() const { return m_groupedMapping; } | 
| +    CompositedLayerMapping* groupedMapping() const { return m_rareData ? m_rareData->groupedMapping : nullptr; } | 
| enum SetGroupMappingOptions { | 
| InvalidateLayerAndRemoveFromMapping, | 
| DoNotInvalidateLayerAndRemoveFromMapping | 
| @@ -466,31 +507,44 @@ public: | 
|  | 
| bool scrollsOverflow() const; | 
|  | 
| -    CompositingReasons potentialCompositingReasonsFromStyle() const { return m_potentialCompositingReasonsFromStyle; } | 
| -    void setPotentialCompositingReasonsFromStyle(CompositingReasons reasons) { ASSERT(reasons == (reasons & CompositingReasonComboAllStyleDeterminedReasons)); m_potentialCompositingReasonsFromStyle = reasons; } | 
| +    CompositingReasons potentialCompositingReasonsFromStyle() const { return m_rareData ? m_rareData->potentialCompositingReasonsFromStyle : CompositingReasonNone; } | 
| +    void setPotentialCompositingReasonsFromStyle(CompositingReasons reasons) | 
| +    { | 
| +        ASSERT(reasons == (reasons & CompositingReasonComboAllStyleDeterminedReasons)); | 
| +        if (m_rareData || reasons != CompositingReasonNone) | 
| +            ensureRareData().potentialCompositingReasonsFromStyle = reasons; | 
| +    } | 
|  | 
| -    bool hasStyleDeterminedDirectCompositingReasons() const { return m_potentialCompositingReasonsFromStyle & CompositingReasonComboAllDirectStyleDeterminedReasons; } | 
| +    bool hasStyleDeterminedDirectCompositingReasons() const { return potentialCompositingReasonsFromStyle() & CompositingReasonComboAllDirectStyleDeterminedReasons; } | 
|  | 
| class AncestorDependentCompositingInputs { | 
| DISALLOW_NEW(); | 
| public: | 
| AncestorDependentCompositingInputs() | 
| -            : opacityAncestor(0) | 
| -            , transformAncestor(0) | 
| -            , filterAncestor(0) | 
| -            , clippingContainer(0) | 
| -            , ancestorScrollingLayer(0) | 
| -            , nearestFixedPositionLayer(0) | 
| -            , scrollParent(0) | 
| -            , clipParent(0) | 
| -            , hasAncestorWithClipPath(false) | 
| +            : clippingContainer(nullptr) | 
| { } | 
|  | 
| IntRect clippedAbsoluteBoundingBox; | 
| +        const LayoutObject* clippingContainer; | 
| +    }; | 
| + | 
| +    class RareAncestorDependentCompositingInputs { | 
| +    public: | 
| +        RareAncestorDependentCompositingInputs() | 
| +            : opacityAncestor(nullptr) | 
| +            , transformAncestor(nullptr) | 
| +            , filterAncestor(nullptr) | 
| +            , ancestorScrollingLayer(nullptr) | 
| +            , nearestFixedPositionLayer(nullptr) | 
| +            , scrollParent(nullptr) | 
| +            , clipParent(nullptr) | 
| +        { } | 
| + | 
| +        bool isDefault() const { return !opacityAncestor && !transformAncestor && !filterAncestor && !ancestorScrollingLayer && !nearestFixedPositionLayer && !scrollParent && !clipParent; } | 
| + | 
| const PaintLayer* opacityAncestor; | 
| const PaintLayer* transformAncestor; | 
| const PaintLayer* filterAncestor; | 
| -        const LayoutObject* clippingContainer; | 
| const PaintLayer* ancestorScrollingLayer; | 
| const PaintLayer* nearestFixedPositionLayer; | 
|  | 
| @@ -508,20 +562,6 @@ public: | 
| // needs to know about clip parents in order to circumvent its normal | 
| // clipping logic. | 
| const PaintLayer* clipParent; | 
| - | 
| -        unsigned hasAncestorWithClipPath : 1; | 
| -    }; | 
| - | 
| -    class DescendantDependentCompositingInputs { | 
| -        DISALLOW_NEW(); | 
| -    public: | 
| -        DescendantDependentCompositingInputs() | 
| -            : hasDescendantWithClipPath(false) | 
| -            , hasNonIsolatedDescendantWithBlendMode(false) | 
| -        { } | 
| - | 
| -        unsigned hasDescendantWithClipPath : 1; | 
| -        unsigned hasNonIsolatedDescendantWithBlendMode : 1; | 
| }; | 
|  | 
| void setNeedsCompositingInputsUpdate(); | 
| @@ -534,30 +574,27 @@ public: | 
| return m_needsDescendantDependentCompositingInputsUpdate; | 
| } | 
|  | 
| -    void updateAncestorDependentCompositingInputs(const AncestorDependentCompositingInputs&); | 
| -    void updateDescendantDependentCompositingInputs(const DescendantDependentCompositingInputs&); | 
| +    void updateAncestorDependentCompositingInputs(const AncestorDependentCompositingInputs&, const RareAncestorDependentCompositingInputs&, bool hasAncestorWithClipPath); | 
| +    void updateDescendantDependentCompositingInputs(bool hasDescendantWithClipPath, bool hasNonIsolatedDescendantWithBlendMode); | 
| void didUpdateCompositingInputs(); | 
|  | 
| -    const AncestorDependentCompositingInputs& ancestorDependentCompositingInputs() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_ancestorDependentCompositingInputs; } | 
| -    const DescendantDependentCompositingInputs& descendantDependentCompositingInputs() const { ASSERT(!m_needsDescendantDependentCompositingInputsUpdate); return m_descendantDependentCompositingInputs; } | 
| - | 
| -    IntRect clippedAbsoluteBoundingBox() const { return ancestorDependentCompositingInputs().clippedAbsoluteBoundingBox; } | 
| -    const PaintLayer* opacityAncestor() const { return ancestorDependentCompositingInputs().opacityAncestor; } | 
| -    const PaintLayer* transformAncestor() const { return ancestorDependentCompositingInputs().transformAncestor; } | 
| -    const PaintLayer* filterAncestor() const { return ancestorDependentCompositingInputs().filterAncestor; } | 
| -    const LayoutObject* clippingContainer() const { return ancestorDependentCompositingInputs().clippingContainer; } | 
| -    const PaintLayer* ancestorScrollingLayer() const { return ancestorDependentCompositingInputs().ancestorScrollingLayer; } | 
| -    const PaintLayer* nearestFixedPositionLayer() const { return ancestorDependentCompositingInputs().nearestFixedPositionLayer; } | 
| -    PaintLayer* scrollParent() const { return const_cast<PaintLayer*>(ancestorDependentCompositingInputs().scrollParent); } | 
| -    PaintLayer* clipParent() const { return const_cast<PaintLayer*>(ancestorDependentCompositingInputs().clipParent); } | 
| -    bool hasAncestorWithClipPath() const { return ancestorDependentCompositingInputs().hasAncestorWithClipPath; } | 
| -    bool hasDescendantWithClipPath() const { return descendantDependentCompositingInputs().hasDescendantWithClipPath; } | 
| +    IntRect clippedAbsoluteBoundingBox() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_ancestorDependentCompositingInputs.clippedAbsoluteBoundingBox; } | 
| +    const PaintLayer* opacityAncestor() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->opacityAncestor : nullptr; } | 
| +    const PaintLayer* transformAncestor() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->transformAncestor : nullptr; } | 
| +    const PaintLayer* filterAncestor() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->filterAncestor : nullptr; } | 
| +    const LayoutObject* clippingContainer() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_ancestorDependentCompositingInputs.clippingContainer; } | 
| +    const PaintLayer* ancestorScrollingLayer() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->ancestorScrollingLayer : nullptr; } | 
| +    const PaintLayer* nearestFixedPositionLayer() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->nearestFixedPositionLayer : nullptr; } | 
| +    const PaintLayer* scrollParent() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->scrollParent : nullptr; } | 
| +    const PaintLayer* clipParent() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_rareAncestorDependentCompositingInputs ? m_rareAncestorDependentCompositingInputs->clipParent : nullptr; } | 
| +    bool hasAncestorWithClipPath() const { ASSERT(!m_needsAncestorDependentCompositingInputsUpdate); return m_hasAncestorWithClipPath; } | 
| +    bool hasDescendantWithClipPath() const { ASSERT(!m_needsDescendantDependentCompositingInputsUpdate); return m_hasDescendantWithClipPath; } | 
| bool hasNonIsolatedDescendantWithBlendMode() const; | 
|  | 
| bool lostGroupedMapping() const { ASSERT(isAllowedToQueryCompositingState()); return m_lostGroupedMapping; } | 
| void setLostGroupedMapping(bool b) { m_lostGroupedMapping = b; } | 
|  | 
| -    CompositingReasons compositingReasons() const { ASSERT(isAllowedToQueryCompositingState()); return m_compositingReasons; } | 
| +    CompositingReasons compositingReasons() const { ASSERT(isAllowedToQueryCompositingState()); return m_rareData ? m_rareData->compositingReasons : CompositingReasonNone; } | 
| void setCompositingReasons(CompositingReasons, CompositingReasons mask = CompositingReasonAll); | 
|  | 
| bool hasCompositingDescendant() const { ASSERT(isAllowedToQueryCompositingState()); return m_hasCompositingDescendant; } | 
| @@ -713,7 +750,14 @@ private: | 
|  | 
| void markCompositingContainerChainForNeedsRepaint(); | 
|  | 
| -    PaintLayerType m_layerType; | 
| +    PaintLayerRareData& ensureRareData() | 
| +    { | 
| +        if (!m_rareData) | 
| +            m_rareData = adoptPtr(new PaintLayerRareData); | 
| +        return *m_rareData; | 
| +    } | 
| + | 
| +    unsigned m_layerType : 2; // PaintLayerType | 
|  | 
| // Self-painting layer is an optimization where we avoid the heavy Layer painting | 
| // machinery for a Layer allocated only to handle the overflow clip case. | 
| @@ -770,6 +814,11 @@ private: | 
| unsigned m_needsPaintPhaseDescendantOutlines : 1; | 
| unsigned m_needsPaintPhaseFloat : 1; | 
|  | 
| +    // These bitfields are part of ancestor/descendant dependent compositing inputs. | 
| +    unsigned m_hasDescendantWithClipPath : 1; | 
| +    unsigned m_hasNonIsolatedDescendantWithBlendMode : 1; | 
| +    unsigned m_hasAncestorWithClipPath : 1; | 
| + | 
| LayoutBoxModelObject* m_layoutObject; | 
|  | 
| PaintLayer* m_parent; | 
| @@ -778,9 +827,6 @@ private: | 
| PaintLayer* m_first; | 
| PaintLayer* m_last; | 
|  | 
| -    // Our current relative position offset. | 
| -    LayoutSize m_offsetForInFlowPosition; | 
| - | 
| // Our (x,y) coordinates are in our parent layer's coordinate space. | 
| LayoutPoint m_location; | 
|  | 
| @@ -794,44 +840,19 @@ private: | 
| LayoutUnit m_staticInlinePosition; | 
| LayoutUnit m_staticBlockPosition; | 
|  | 
| -    OwnPtr<TransformationMatrix> m_transform; | 
| - | 
| -    // Pointer to the enclosing Layer that caused us to be paginated. It is 0 if we are not paginated. | 
| -    // | 
| -    // See LayoutMultiColumnFlowThread and | 
| -    // https://sites.google.com/a/chromium.org/dev/developers/design-documents/multi-column-layout | 
| -    // for more information about the multicol implementation. It's important to understand the | 
| -    // difference between flow thread coordinates and visual coordinates when working with multicol | 
| -    // in Layer, since Layer is one of the few places where we have to worry about the | 
| -    // visual ones. Internally we try to use flow-thread coordinates whenever possible. | 
| -    PaintLayer* m_enclosingPaginationLayer; | 
| - | 
| -    // These compositing reasons are updated whenever style changes, not while updating compositing layers. | 
| -    // They should not be used to infer the compositing state of this layer. | 
| -    CompositingReasons m_potentialCompositingReasonsFromStyle; | 
| - | 
| -    // Once computed, indicates all that a layer needs to become composited using the CompositingReasons enum bitfield. | 
| -    CompositingReasons m_compositingReasons; | 
| - | 
| -    DescendantDependentCompositingInputs m_descendantDependentCompositingInputs; | 
| AncestorDependentCompositingInputs m_ancestorDependentCompositingInputs; | 
| +    OwnPtr<RareAncestorDependentCompositingInputs> m_rareAncestorDependentCompositingInputs; | 
|  | 
| -    IntRect m_blockSelectionGapsBounds; | 
| - | 
| -    OwnPtr<CompositedLayerMapping> m_compositedLayerMapping; | 
| OwnPtrWillBePersistent<PaintLayerScrollableArea> m_scrollableArea; | 
|  | 
| -    CompositedLayerMapping* m_groupedMapping; | 
| - | 
| PaintLayerClipper m_clipper; // FIXME: Lazily allocate? | 
| OwnPtr<PaintLayerStackingNode> m_stackingNode; | 
| -    OwnPtr<PaintLayerReflectionInfo> m_reflectionInfo; | 
| - | 
| -    LayoutSize m_subpixelAccumulation; // The accumulated subpixel offset of a composited layer's composited bounds compared to absolute coordinates. | 
|  | 
| IntSize m_previousScrollOffsetAccumulationForPainting; | 
| RefPtr<ClipRects> m_previousPaintingClipRects; | 
| LayoutRect m_previousPaintDirtyRect; | 
| + | 
| +    OwnPtr<PaintLayerRareData> m_rareData; | 
| }; | 
|  | 
| } // namespace blink | 
|  |