acb601c9e886d6ffc2c0681a0d11bb296de52f2a
[WebKit-https.git] / Source / WebCore / page / scrolling / ScrollingStateNode.h
1 /*
2  * Copyright (C) 2012 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef ScrollingStateNode_h
27 #define ScrollingStateNode_h
28
29 #if ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
30
31 #include "GraphicsLayer.h"
32 #include "ScrollingCoordinator.h"
33 #include <wtf/RefCounted.h>
34 #include <wtf/TypeCasts.h>
35 #include <wtf/Vector.h>
36
37 namespace WebCore {
38
39 class GraphicsLayer;
40 class ScrollingStateTree;
41 class TextStream;
42
43 // Used to allow ScrollingStateNodes to refer to layers in various contexts:
44 // a) Async scrolling, main thread: ScrollingStateNode holds onto a GraphicsLayer, and uses m_layerID
45 //    to detect whether that GraphicsLayer's underlying PlatformLayer changed.
46 // b) Threaded scrolling, commit to scrolling thread: ScrollingStateNode wraps a PlatformLayer, which
47 //    can be passed to the Scrolling Thread
48 // c) Remote scrolling UI process, where LayerRepresentation wraps just a PlatformLayerID.
49 class LayerRepresentation {
50 public:
51     enum Type {
52         EmptyRepresentation,
53         GraphicsLayerRepresentation,
54         PlatformLayerRepresentation,
55         PlatformLayerIDRepresentation
56     };
57
58     LayerRepresentation()
59         : m_graphicsLayer(nullptr)
60         , m_layerID(0)
61         , m_representation(EmptyRepresentation)
62     { }
63
64     LayerRepresentation(GraphicsLayer* graphicsLayer)
65         : m_graphicsLayer(graphicsLayer)
66         , m_layerID(graphicsLayer ? graphicsLayer->primaryLayerID() : 0)
67         , m_representation(GraphicsLayerRepresentation)
68     { }
69
70     LayerRepresentation(PlatformLayer* platformLayer)
71         : m_platformLayer(platformLayer)
72         , m_layerID(0)
73         , m_representation(PlatformLayerRepresentation)
74     {
75         retainPlatformLayer(platformLayer);
76     }
77
78     LayerRepresentation(GraphicsLayer::PlatformLayerID layerID)
79         : m_graphicsLayer(nullptr)
80         , m_layerID(layerID)
81         , m_representation(PlatformLayerIDRepresentation)
82     {
83     }
84
85     LayerRepresentation(const LayerRepresentation& other)
86         : m_platformLayer(other.m_platformLayer)
87         , m_layerID(other.m_layerID)
88         , m_representation(other.m_representation)
89     {
90         if (m_representation == PlatformLayerRepresentation)
91             retainPlatformLayer(m_platformLayer);
92     }
93
94     ~LayerRepresentation()
95     {
96         if (m_representation == PlatformLayerRepresentation)
97             releasePlatformLayer(m_platformLayer);
98     }
99
100     operator GraphicsLayer*() const
101     {
102         ASSERT(m_representation == GraphicsLayerRepresentation);
103         return m_graphicsLayer;
104     }
105
106     operator PlatformLayer*() const
107     {
108         ASSERT(m_representation == PlatformLayerRepresentation);
109         return m_platformLayer;
110     }
111     
112     GraphicsLayer::PlatformLayerID layerID() const
113     {
114         return m_layerID;
115     }
116
117     operator GraphicsLayer::PlatformLayerID() const
118     {
119         ASSERT(m_representation != PlatformLayerRepresentation);
120         return m_layerID;
121     }
122
123     LayerRepresentation& operator=(const LayerRepresentation& other)
124     {
125         m_platformLayer = other.m_platformLayer;
126         m_layerID = other.m_layerID;
127         m_representation = other.m_representation;
128
129         if (m_representation == PlatformLayerRepresentation)
130             retainPlatformLayer(m_platformLayer);
131
132         return *this;
133     }
134
135     bool operator==(const LayerRepresentation& other) const
136     {
137         if (m_representation != other.m_representation)
138             return false;
139         switch (m_representation) {
140         case EmptyRepresentation:
141             return true;
142         case GraphicsLayerRepresentation:
143             return m_graphicsLayer == other.m_graphicsLayer
144                 && m_layerID == other.m_layerID;
145         case PlatformLayerRepresentation:
146             return m_platformLayer == other.m_platformLayer;
147         case PlatformLayerIDRepresentation:
148             return m_layerID == other.m_layerID;
149         }
150         ASSERT_NOT_REACHED();
151         return true;
152     }
153     
154     LayerRepresentation toRepresentation(Type representation) const
155     {
156         switch (representation) {
157         case EmptyRepresentation:
158             return LayerRepresentation();
159         case GraphicsLayerRepresentation:
160             ASSERT(m_representation == GraphicsLayerRepresentation);
161             return *this;
162         case PlatformLayerRepresentation:
163             return m_graphicsLayer ? m_graphicsLayer->platformLayer() : nullptr;
164         case PlatformLayerIDRepresentation:
165             return LayerRepresentation(m_layerID);
166         }
167         return LayerRepresentation();
168     }
169
170     bool representsGraphicsLayer() const { return m_representation == GraphicsLayerRepresentation; }
171     bool representsPlatformLayerID() const { return m_representation == PlatformLayerIDRepresentation; }
172     
173 private:
174     WEBCORE_EXPORT void retainPlatformLayer(PlatformLayer*);
175     WEBCORE_EXPORT void releasePlatformLayer(PlatformLayer*);
176
177     union {
178         GraphicsLayer* m_graphicsLayer;
179         PlatformLayer *m_platformLayer;
180     };
181
182     GraphicsLayer::PlatformLayerID m_layerID;
183     Type m_representation;
184 };
185
186 class ScrollingStateNode : public RefCounted<ScrollingStateNode> {
187     WTF_MAKE_FAST_ALLOCATED;
188 public:
189     ScrollingStateNode(ScrollingNodeType, ScrollingStateTree&, ScrollingNodeID);
190     virtual ~ScrollingStateNode();
191     
192     ScrollingNodeType nodeType() const { return m_nodeType; }
193
194     bool isFixedNode() const { return m_nodeType == FixedNode; }
195     bool isStickyNode() const { return m_nodeType == StickyNode; }
196     bool isScrollingNode() const { return m_nodeType == FrameScrollingNode || m_nodeType == OverflowScrollingNode; }
197     bool isFrameScrollingNode() const { return m_nodeType == FrameScrollingNode; }
198     bool isOverflowScrollingNode() const { return m_nodeType == OverflowScrollingNode; }
199
200     virtual Ref<ScrollingStateNode> clone(ScrollingStateTree& adoptiveTree) = 0;
201     PassRefPtr<ScrollingStateNode> cloneAndReset(ScrollingStateTree& adoptiveTree);
202     void cloneAndResetChildren(ScrollingStateNode&, ScrollingStateTree& adoptiveTree);
203
204     enum {
205         ScrollLayer = 0,
206         NumStateNodeBits = 1
207     };
208     typedef unsigned ChangedProperties;
209
210     bool hasChangedProperties() const { return m_changedProperties; }
211     bool hasChangedProperty(unsigned propertyBit) const { return m_changedProperties & (1 << propertyBit); }
212     void resetChangedProperties() { m_changedProperties = 0; }
213     void setPropertyChanged(unsigned propertyBit);
214
215     ChangedProperties changedProperties() const { return m_changedProperties; }
216     void setChangedProperties(ChangedProperties changedProperties) { m_changedProperties = changedProperties; }
217     
218     virtual void syncLayerPositionForViewportRect(const LayoutRect& /*viewportRect*/) { }
219
220     const LayerRepresentation& layer() const { return m_layer; }
221     WEBCORE_EXPORT void setLayer(const LayerRepresentation&);
222
223     ScrollingStateTree& scrollingStateTree() const { return m_scrollingStateTree; }
224
225     ScrollingNodeID scrollingNodeID() const { return m_nodeID; }
226
227     ScrollingStateNode* parent() const { return m_parent; }
228     void setParent(ScrollingStateNode* parent) { m_parent = parent; }
229     ScrollingNodeID parentNodeID() const { return m_parent ? m_parent->scrollingNodeID() : 0; }
230
231     Vector<RefPtr<ScrollingStateNode>>* children() const { return m_children.get(); }
232
233     void appendChild(PassRefPtr<ScrollingStateNode>);
234
235     String scrollingStateTreeAsText() const;
236
237 protected:
238     ScrollingStateNode(const ScrollingStateNode&, ScrollingStateTree&);
239
240 private:
241     void dump(TextStream&, int indent) const;
242
243     virtual void dumpProperties(TextStream&, int indent) const = 0;
244
245     const ScrollingNodeType m_nodeType;
246     ScrollingNodeID m_nodeID;
247     ChangedProperties m_changedProperties;
248
249     ScrollingStateTree& m_scrollingStateTree;
250
251     ScrollingStateNode* m_parent;
252     std::unique_ptr<Vector<RefPtr<ScrollingStateNode>>> m_children;
253
254     LayerRepresentation m_layer;
255 };
256
257 } // namespace WebCore
258
259 #define SPECIALIZE_TYPE_TRAITS_SCROLLING_STATE_NODE(ToValueTypeName, predicate) \
260 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
261     static bool isType(const WebCore::ScrollingStateNode& node) { return node.predicate; } \
262 SPECIALIZE_TYPE_TRAITS_END()
263
264 #endif // ENABLE(ASYNC_SCROLLING) || USE(COORDINATED_GRAPHICS)
265
266 #endif // ScrollingStateNode_h