OSDN Git Service

5fd3b7c4b27f5833073c65240a8c1a88de3611eb
[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 "TilesManager.h"
32
33 #include <cutils/log.h>
34 #include <wtf/CurrentTime.h>
35 #include <wtf/text/CString.h>
36
37 #undef XLOGC
38 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
39
40 #ifdef DEBUG
41
42 #undef XLOG
43 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
44
45 #else
46
47 #undef XLOG
48 #define XLOG(...)
49
50 #endif // DEBUG
51
52 namespace WebCore {
53
54 TreeManager::TreeManager()
55     : m_drawingTree(0)
56     , m_paintingTree(0)
57     , m_queuedTree(0)
58     , m_fastSwapMode(false)
59 {
60 }
61
62 TreeManager::~TreeManager()
63 {
64     clearTrees();
65 }
66
67 // the painting tree has finished painting:
68 //   discard the drawing tree
69 //   swap the painting tree in place of the drawing tree
70 //   and start painting the queued tree
71 void TreeManager::swap()
72 {
73     // swap can't be called unless painting just finished
74     ASSERT(m_paintingTree);
75
76     android::Mutex::Autolock lock(m_paintSwapLock);
77
78     XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
79
80     // if we have a drawing tree, discard it since the painting tree is done
81     if (m_drawingTree) {
82         XLOG("destroying drawing tree %p", m_drawingTree);
83         m_drawingTree->setIsDrawing(false);
84         SkSafeUnref(m_drawingTree);
85     }
86
87     // painting tree becomes the drawing tree
88     XLOG("drawing tree %p", m_paintingTree);
89     m_paintingTree->setIsDrawing(true);
90
91     if (m_queuedTree) {
92         // start painting with the queued tree
93         XLOG("now painting tree %p", m_queuedTree);
94         m_queuedTree->setIsPainting(m_paintingTree);
95     }
96     m_drawingTree = m_paintingTree;
97     m_paintingTree = m_queuedTree;
98     m_queuedTree = 0;
99
100     TilesManager::instance()->paintedSurfacesCleanup();
101
102     XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
103 }
104
105 // clear all of the content in the three trees held by the tree manager
106 void TreeManager::clearTrees()
107 {
108     // remove painted surfaces from any tree in this view, and set trees as no
109     // longer drawing, to clear ptrs from surfaces to layers
110     GLWebViewState* oldState = 0;
111     if (m_drawingTree) {
112         oldState = m_drawingTree->state();
113         m_drawingTree->setIsDrawing(false);
114     }
115     if (m_paintingTree) {
116         oldState = m_paintingTree->state();
117         m_paintingTree->setIsDrawing(false);
118     }
119
120     XLOG("TreeManager %p removing PS from state %p", this, oldState);
121     TilesManager::instance()->paintedSurfacesCleanup(oldState);
122
123     SkSafeUnref(m_drawingTree);
124     m_drawingTree = 0;
125     SkSafeUnref(m_paintingTree);
126     m_paintingTree = 0;
127     SkSafeUnref(m_queuedTree);
128     m_queuedTree = 0;
129 }
130
131 // a new layer tree has arrived, queue it if we're painting something already,
132 // or start painting it if we aren't
133 void TreeManager::updateWithTree(Layer* newTree, bool brandNew)
134 {
135
136     // can't have a queued tree unless have a painting tree too
137     ASSERT(m_paintingTree || !m_queuedTree);
138
139     SkSafeRef(newTree);
140
141     android::Mutex::Autolock lock(m_paintSwapLock);
142
143     if (!newTree || brandNew) {
144         clearTrees();
145         if (brandNew) {
146             m_animationOffset = 0;
147             m_isAnimating = false;
148             m_lastFrameTime = WTF::currentTime();
149
150             m_paintingTree = newTree;
151             m_paintingTree->setIsPainting(m_drawingTree);
152         }
153         return;
154     }
155
156     if (m_queuedTree || m_paintingTree) {
157         // currently painting, so defer this new tree
158         if (m_queuedTree) {
159             // have a queued tree, copy over invals so the regions are
160             // eventually repainted
161             m_queuedTree->mergeInvalsInto(newTree);
162         }
163         SkSafeUnref(m_queuedTree);
164         m_queuedTree = newTree;
165         return;
166     }
167
168     // don't have painting tree, paint this one!
169     m_paintingTree = newTree;
170     m_paintingTree->setIsPainting(m_drawingTree);
171 }
172
173 bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
174                          SkRect& visibleRect, float scale,
175                          bool enterFastSwapMode, bool* buffersSwappedPtr,
176                          TexturesResult* texturesResultPtr)
177 {
178     m_fastSwapMode |= enterFastSwapMode;
179
180     XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
181          m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);
182
183     bool ret = false;
184     bool didTreeSwap = false;
185     if (m_paintingTree) {
186         ret |= m_paintingTree->prepare(currentTime, viewRect,
187                                        visibleRect, scale);
188
189         if (m_paintingTree->countChildren()) {
190             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
191             laTree->computeTexturesAmount(texturesResultPtr);
192         }
193         if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
194             XLOG("have painting tree %p ready, swapping!", m_paintingTree);
195             didTreeSwap = true;
196             swap();
197             if (buffersSwappedPtr)
198                 *buffersSwappedPtr = true;
199         }
200     } else if (m_drawingTree) {
201         XLOG("preparing drawing tree %p", m_drawingTree);
202         ret |= m_drawingTree->prepare(currentTime, viewRect,
203                                       visibleRect, scale);
204         if (m_drawingTree->countChildren()) {
205             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
206             laTree->computeTexturesAmount(texturesResultPtr);
207         }
208     }
209
210     if (!m_isAnimating) {
211         m_animationOffset += currentTime - m_lastFrameTime;
212 #ifdef ANIM_DEBUG
213         XLOGC("adding to %f", m_animationOffset);
214 #endif
215     }
216
217     if (m_drawingTree) {
218         bool drawingReady = didTreeSwap || m_drawingTree->isReady();
219
220         if (drawingReady || m_fastSwapMode)
221             m_drawingTree->swapTiles();
222
223         if (drawingReady) {
224             // exit fast swap mode, as content is up to date
225             m_fastSwapMode = false;
226         } else {
227             // drawing isn't ready, must redraw
228             ret = true;
229         }
230
231         if (m_drawingTree->countChildren()) {
232 #ifdef ANIM_DEBUG
233             XLOGC("drawing tree %p with animation time offset of %f, locked %d",
234                   m_drawingTree, m_animationOffset, m_isAnimating);
235 #endif
236             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
237             m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset);
238             if (!m_isAnimating)
239                 m_animationOffset = 0;
240             ret |= m_isAnimating;
241         } else if (!m_paintingTree) {
242             m_animationOffset = 0;
243             m_isAnimating = false;
244         }
245         XLOG("drawing tree %p", m_drawingTree);
246         ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
247     } else if (m_paintingTree && m_paintingTree->state()) {
248         // Dont have a drawing tree, draw white background
249         Color defaultBackground = Color::white;
250         m_paintingTree->state()->drawBackground(defaultBackground);
251     }
252
253     m_lastFrameTime = currentTime;
254
255     if (m_paintingTree) {
256         XLOG("still have painting tree %p", m_paintingTree);
257         return true;
258     }
259
260     return ret;
261 }
262
263 int TreeManager::getTotalPaintedSurfaceCount()
264 {
265     return TilesManager::instance()->getPaintedSurfaceCount();
266 }
267
268 // draw for base tile - called on TextureGeneration thread
269 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
270 {
271     BaseLayerAndroid* paintingTree = 0;
272     m_paintSwapLock.lock();
273     if (m_paintingTree)
274         paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
275     else
276         paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
277     SkSafeRef(paintingTree);
278     m_paintSwapLock.unlock();
279
280     if (!paintingTree)
281         return;
282
283
284     paintingTree->drawCanvas(canvas);
285
286     if (drawLayers && paintingTree->countChildren()) {
287         // draw the layers onto the canvas as well
288         Layer* layers = paintingTree->getChild(0);
289         static_cast<LayerAndroid*>(layers)->drawCanvas(canvas);
290     }
291
292     SkSafeUnref(paintingTree);
293 }
294
295 int TreeManager::baseContentWidth()
296 {
297     if (m_paintingTree) {
298         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->width();
299     } else if (m_drawingTree) {
300         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->width();
301     }
302     return 0;
303 }
304
305 int TreeManager::baseContentHeight()
306 {
307     if (m_paintingTree) {
308         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->height();
309     } else if (m_drawingTree) {
310         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->height();
311     }
312     return 0;
313 }
314
315 } // namespace WebCore