OSDN Git Service

Scroll position now passed to all layers
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / TreeManager.cpp
1 /*
2  * Copyright 2011, The Android Open Source Project
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  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "TreeManager.h"
28
29 #include "Layer.h"
30 #include "BaseLayerAndroid.h"
31 #include "ScrollableLayerAndroid.h"
32 #include "TilesManager.h"
33
34 #include <cutils/log.h>
35 #include <wtf/CurrentTime.h>
36 #include <wtf/text/CString.h>
37
38 #undef XLOGC
39 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
40
41 #ifdef DEBUG
42
43 #undef XLOG
44 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
45
46 #else
47
48 #undef XLOG
49 #define XLOG(...)
50
51 #endif // DEBUG
52
53 namespace WebCore {
54
55 TreeManager::TreeManager()
56     : m_drawingTree(0)
57     , m_paintingTree(0)
58     , m_queuedTree(0)
59     , m_fastSwapMode(false)
60 {
61 }
62
63 TreeManager::~TreeManager()
64 {
65     clearTrees();
66 }
67
68 // the painting tree has finished painting:
69 //   discard the drawing tree
70 //   swap the painting tree in place of the drawing tree
71 //   and start painting the queued tree
72 void TreeManager::swap()
73 {
74     // swap can't be called unless painting just finished
75     ASSERT(m_paintingTree);
76
77     android::Mutex::Autolock lock(m_paintSwapLock);
78
79     XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
80
81     // if we have a drawing tree, discard it since the painting tree is done
82     if (m_drawingTree) {
83         XLOG("destroying drawing tree %p", m_drawingTree);
84         m_drawingTree->setIsDrawing(false);
85         SkSafeUnref(m_drawingTree);
86     }
87
88     // painting tree becomes the drawing tree
89     XLOG("drawing tree %p", m_paintingTree);
90     m_paintingTree->setIsDrawing(true);
91
92     if (m_queuedTree) {
93         // start painting with the queued tree
94         XLOG("now painting tree %p", m_queuedTree);
95         m_queuedTree->setIsPainting(m_paintingTree);
96     }
97     m_drawingTree = m_paintingTree;
98     m_paintingTree = m_queuedTree;
99     m_queuedTree = 0;
100
101     TilesManager::instance()->paintedSurfacesCleanup();
102
103     XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
104 }
105
106 // clear all of the content in the three trees held by the tree manager
107 void TreeManager::clearTrees()
108 {
109     // remove painted surfaces from any tree in this view, and set trees as no
110     // longer drawing, to clear ptrs from surfaces to layers
111     GLWebViewState* oldState = 0;
112     if (m_drawingTree) {
113         oldState = m_drawingTree->state();
114         m_drawingTree->setIsDrawing(false);
115     }
116     if (m_paintingTree) {
117         oldState = m_paintingTree->state();
118         m_paintingTree->setIsDrawing(false);
119     }
120
121     XLOG("TreeManager %p removing PS from state %p", this, oldState);
122     TilesManager::instance()->paintedSurfacesCleanup(oldState);
123
124     SkSafeUnref(m_drawingTree);
125     m_drawingTree = 0;
126     SkSafeUnref(m_paintingTree);
127     m_paintingTree = 0;
128     SkSafeUnref(m_queuedTree);
129     m_queuedTree = 0;
130 }
131
132 // a new layer tree has arrived, queue it if we're painting something already,
133 // or start painting it if we aren't
134 void TreeManager::updateWithTree(Layer* newTree, bool brandNew)
135 {
136     XLOG("updateWithTree - %p, has children %d, has animations %d",
137          newTree, newTree && newTree->countChildren(),
138          newTree && newTree->countChildren()
139              ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
140
141     // can't have a queued tree unless have a painting tree too
142     ASSERT(m_paintingTree || !m_queuedTree);
143
144     SkSafeRef(newTree);
145
146     android::Mutex::Autolock lock(m_paintSwapLock);
147
148     if (!newTree || brandNew) {
149         clearTrees();
150         if (brandNew) {
151             m_paintingTree = newTree;
152             m_paintingTree->setIsPainting(m_drawingTree);
153         }
154         return;
155     }
156
157     if (m_queuedTree || m_paintingTree) {
158         // currently painting, so defer this new tree
159         if (m_queuedTree) {
160             // have a queued tree, copy over invals so the regions are
161             // eventually repainted
162             m_queuedTree->mergeInvalsInto(newTree);
163
164             XLOG("DISCARDING tree - %p, has children %d, has animations %d",
165                  newTree, newTree && newTree->countChildren(),
166                  newTree && newTree->countChildren()
167                      ? static_cast<LayerAndroid*>(newTree->getChild(0))->hasAnimations() : 0);
168         }
169         SkSafeUnref(m_queuedTree);
170         m_queuedTree = newTree;
171         return;
172     }
173
174     // don't have painting tree, paint this one!
175     m_paintingTree = newTree;
176     m_paintingTree->setIsPainting(m_drawingTree);
177 }
178
179 void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y)
180 {
181     LayerAndroid* layer;
182     if (tree && tree->countChildren()) {
183         layer = static_cast<LayerAndroid*>(tree->getChild(0))->findById(layerId);
184         if (layer && layer->contentIsScrollable())
185             static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
186     }
187 }
188
189 void TreeManager::updateScrollableLayer(int layerId, int x, int y)
190 {
191     updateScrollableLayerInTree(m_queuedTree, layerId, x, y);
192     updateScrollableLayerInTree(m_paintingTree, layerId, x, y);
193     updateScrollableLayerInTree(m_drawingTree, layerId, x, y);
194 }
195
196 bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
197                          SkRect& visibleRect, float scale,
198                          bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
199                          TexturesResult* texturesResultPtr)
200 {
201     m_fastSwapMode |= enterFastSwapMode;
202
203     XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
204          m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);
205
206     bool ret = false;
207     bool didTreeSwap = false;
208     if (m_paintingTree) {
209         ret |= m_paintingTree->prepare(currentTime, viewRect,
210                                        visibleRect, scale);
211         LayerAndroid* laTree = 0;
212
213         if (m_paintingTree->countChildren()) {
214             laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
215             laTree->computeTexturesAmount(texturesResultPtr);
216         }
217         if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
218             XLOG("have painting tree %p ready, swapping!", m_paintingTree);
219             didTreeSwap = true;
220             swap();
221             if (treesSwappedPtr)
222                 *treesSwappedPtr = true;
223             if (laTree && newTreeHasAnimPtr)
224                 *newTreeHasAnimPtr = laTree->hasAnimations();
225         }
226     } else if (m_drawingTree) {
227         XLOG("preparing drawing tree %p", m_drawingTree);
228         ret |= m_drawingTree->prepare(currentTime, viewRect,
229                                       visibleRect, scale);
230         if (m_drawingTree->countChildren()) {
231             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
232             laTree->computeTexturesAmount(texturesResultPtr);
233         }
234     }
235
236
237     if (m_drawingTree) {
238         bool drawingReady = didTreeSwap || m_drawingTree->isReady();
239
240         if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree))
241             m_drawingTree->swapTiles();
242
243         if (drawingReady) {
244             // exit fast swap mode, as content is up to date
245             m_fastSwapMode = false;
246         } else {
247             // drawing isn't ready, must redraw
248             ret = true;
249         }
250
251         if (m_drawingTree->countChildren()) {
252             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
253             ret |= laTree->evaluateAnimations(currentTime);
254         }
255         XLOG("drawing tree %p", m_drawingTree);
256         ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
257     } else if (m_paintingTree && m_paintingTree->state()) {
258         // Dont have a drawing tree, draw white background
259         Color defaultBackground = Color::white;
260         m_paintingTree->state()->drawBackground(defaultBackground);
261     }
262
263     if (m_paintingTree) {
264         XLOG("still have painting tree %p", m_paintingTree);
265         return true;
266     }
267
268     return ret;
269 }
270
271 int TreeManager::getTotalPaintedSurfaceCount()
272 {
273     return TilesManager::instance()->getPaintedSurfaceCount();
274 }
275
276 // draw for base tile - called on TextureGeneration thread
277 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
278 {
279     BaseLayerAndroid* paintingTree = 0;
280     m_paintSwapLock.lock();
281     if (m_paintingTree)
282         paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
283     else
284         paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
285     SkSafeRef(paintingTree);
286     m_paintSwapLock.unlock();
287
288     if (!paintingTree)
289         return;
290
291
292     paintingTree->drawCanvas(canvas);
293
294     if (drawLayers && paintingTree->countChildren()) {
295         // draw the layers onto the canvas as well
296         Layer* layers = paintingTree->getChild(0);
297         static_cast<LayerAndroid*>(layers)->drawCanvas(canvas);
298     }
299
300     SkSafeUnref(paintingTree);
301 }
302
303 int TreeManager::baseContentWidth()
304 {
305     if (m_paintingTree) {
306         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->width();
307     } else if (m_drawingTree) {
308         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->width();
309     }
310     return 0;
311 }
312
313 int TreeManager::baseContentHeight()
314 {
315     if (m_paintingTree) {
316         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->height();
317     } else if (m_drawingTree) {
318         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->height();
319     }
320     return 0;
321 }
322
323 } // namespace WebCore