5119ccc5e1a313e761902027caa739da6f34ad07
[WebKit-https.git] / Source / WebCore / inspector / InspectorLayerTreeAgent.cpp
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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32
33 #if USE(ACCELERATED_COMPOSITING)
34 #if ENABLE(INSPECTOR)
35
36 #include "InspectorLayerTreeAgent.h"
37
38 #include "IdentifiersFactory.h"
39 #include "InspectorDOMAgent.h"
40 #include "InspectorFrontend.h"
41 #include "InspectorState.h"
42 #include "InstrumentingAgents.h"
43 #include "IntRect.h"
44 #include "RenderLayer.h"
45 #include "RenderLayerBacking.h"
46 #include "RenderView.h"
47
48 namespace WebCore {
49
50 namespace LayerTreeAgentState {
51 static const char layerTreeAgentEnabled[] = "layerTreeAgentEnabled";
52 };
53
54 InspectorLayerTreeAgent::InspectorLayerTreeAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state)
55     : InspectorBaseAgent<InspectorLayerTreeAgent>("LayerTree", instrumentingAgents, state)
56     , m_frontend(0)
57 {
58 }
59
60 InspectorLayerTreeAgent::~InspectorLayerTreeAgent()
61 {
62     reset();
63 }
64
65 void InspectorLayerTreeAgent::setFrontend(InspectorFrontend* frontend)
66 {
67     m_frontend = frontend->layertree();
68 }
69
70 void InspectorLayerTreeAgent::clearFrontend()
71 {
72     m_frontend = 0;
73     disable(0);
74 }
75
76 void InspectorLayerTreeAgent::restore()
77 {
78     if (m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
79         enable(0);
80 }
81
82 void InspectorLayerTreeAgent::reset()
83 {
84     m_documentLayerToIdMap.clear();
85     m_idToLayer.clear();
86 }
87
88 void InspectorLayerTreeAgent::enable(ErrorString*)
89 {
90     m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, true);
91     m_instrumentingAgents->setInspectorLayerTreeAgent(this);
92 }
93
94 void InspectorLayerTreeAgent::disable(ErrorString*)
95 {
96     if (!m_state->getBoolean(LayerTreeAgentState::layerTreeAgentEnabled))
97         return;
98     m_state->setBoolean(LayerTreeAgentState::layerTreeAgentEnabled, false);
99     m_instrumentingAgents->setInspectorLayerTreeAgent(0);
100 }
101
102 void InspectorLayerTreeAgent::layerTreeDidChange()
103 {
104     m_frontend->layerTreeDidChange();
105 }
106
107 void InspectorLayerTreeAgent::renderLayerDestroyed(const RenderLayer* renderLayer)
108 {
109     unbind(renderLayer);
110 }
111
112 void InspectorLayerTreeAgent::layersForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
113 {
114     layers = TypeBuilder::Array<TypeBuilder::LayerTree::Layer>::create();
115
116     Node* node = m_instrumentingAgents->inspectorDOMAgent()->nodeForId(nodeId);
117     if (!node) {
118         *errorString = "Provided node id doesn't match any known node";
119         return;
120     }
121
122     RenderObject* renderer = node->renderer();
123     if (!renderer) {
124         *errorString = "Node for provided node id doesn't have a renderer";
125         return;
126     }
127
128     gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers);
129 }
130
131 void InspectorLayerTreeAgent::gatherLayersUsingRenderObjectHierarchy(ErrorString* errorString, RenderObject* renderer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
132 {
133     if (renderer->hasLayer()) {
134         gatherLayersUsingRenderLayerHierarchy(errorString, toRenderLayerModelObject(renderer)->layer(), layers);
135         return;
136     }
137
138     for (renderer = renderer->firstChild(); renderer; renderer = renderer->nextSibling())
139         gatherLayersUsingRenderObjectHierarchy(errorString, renderer, layers);
140 }
141
142 void InspectorLayerTreeAgent::gatherLayersUsingRenderLayerHierarchy(ErrorString* errorString, RenderLayer* renderLayer, RefPtr<TypeBuilder::Array<TypeBuilder::LayerTree::Layer> >& layers)
143 {
144     if (renderLayer->isComposited())
145         layers->addItem(buildObjectForLayer(errorString, renderLayer));
146
147     for (renderLayer = renderLayer->firstChild(); renderLayer; renderLayer = renderLayer->nextSibling())
148         gatherLayersUsingRenderLayerHierarchy(errorString, renderLayer, layers);
149 }
150
151 PassRefPtr<TypeBuilder::LayerTree::Layer> InspectorLayerTreeAgent::buildObjectForLayer(ErrorString* errorString, RenderLayer* renderLayer)
152 {
153     bool isReflection = renderLayer->isReflection();
154
155     RenderObject* renderer = renderLayer->renderer();
156     RenderLayerBacking* backing = renderLayer->backing();
157     Node* node = isReflection ? renderer->parent()->node() : renderer->node();
158
159     // Basic set of properties.
160     RefPtr<TypeBuilder::LayerTree::Layer> layerObject = TypeBuilder::LayerTree::Layer::create()
161         .setLayerId(bind(renderLayer))
162         .setNodeId(idForNode(errorString, node))
163         .setBounds(buildObjectForIntRect(enclosingIntRect(renderer->absoluteBoundingBoxRect())))
164         .setMemory(backing->backingStoreMemoryEstimate())
165         .setCompositedBounds(buildObjectForIntRect(backing->compositedBounds()))
166         .setPaintCount(backing->graphicsLayer()->repaintCount());
167
168     if (node && node->shadowHost())
169         layerObject->setIsInShadowTree(true);
170
171     if (isReflection)
172         layerObject->setIsReflection(true);
173
174     return layerObject;
175 }
176
177 int InspectorLayerTreeAgent::idForNode(ErrorString* errorString, Node* node)
178 {
179     InspectorDOMAgent* domAgent = m_instrumentingAgents->inspectorDOMAgent();
180     
181     int nodeId = domAgent->boundNodeId(node);
182     if (!nodeId)
183         nodeId = domAgent->pushNodeToFrontend(errorString, domAgent->boundNodeId(node->document()), node);
184
185     return nodeId;
186 }
187
188 PassRefPtr<TypeBuilder::LayerTree::IntRect> InspectorLayerTreeAgent::buildObjectForIntRect(const IntRect& rect)
189 {
190     return TypeBuilder::LayerTree::IntRect::create()
191         .setX(rect.x())
192         .setY(rect.y())
193         .setWidth(rect.width())
194         .setHeight(rect.height()).release();
195 }
196
197 String InspectorLayerTreeAgent::bind(const RenderLayer* layer)
198 {
199     if (!layer)
200         return "";
201     String identifier = m_documentLayerToIdMap.get(layer);
202     if (identifier.isNull()) {
203         identifier = IdentifiersFactory::createIdentifier();
204         m_documentLayerToIdMap.set(layer, identifier);
205         m_idToLayer.set(identifier, layer);
206     }
207     return identifier;
208 }
209
210 void InspectorLayerTreeAgent::unbind(const RenderLayer* layer)
211 {
212     String identifier = m_documentLayerToIdMap.get(layer);
213     if (identifier.isNull())
214         return;
215
216     m_documentLayerToIdMap.remove(layer);
217     m_idToLayer.remove(identifier);
218 }
219
220 } // namespace WebCore
221
222 #endif // ENABLE(INSPECTOR)
223 #endif // USE(ACCELERATED_COMPOSITING)