OSDN Git Service

synchronous layer updates, and animation deferral during paint
[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_fastSwapMode && */ m_paintingTree->isReady()) {
190             XLOG("have painting tree %p ready, swapping!", m_paintingTree);
191             didTreeSwap = true;
192             swap();
193             if (buffersSwappedPtr)
194                 *buffersSwappedPtr = true;
195         }
196     } else if (m_drawingTree) {
197         XLOG("preparing drawing tree %p", m_drawingTree);
198         ret |= m_drawingTree->prepare(currentTime, viewRect,
199                                       visibleRect, scale);
200     }
201
202     if (!m_isAnimating) {
203         m_animationOffset += currentTime - m_lastFrameTime;
204 #ifdef ANIM_DEBUG
205         XLOGC("adding to %f", m_animationOffset);
206 #endif
207     }
208
209     if (m_drawingTree) {
210         bool drawingReady = didTreeSwap || m_drawingTree->isReady();
211
212         if (didTreeSwap || m_fastSwapMode)
213             m_drawingTree->swapTiles();
214
215         if (drawingReady) {
216             // exit fast swap mode, as content is up to date
217             m_fastSwapMode = false;
218         } else {
219             // drawing isn't ready, must redraw
220             ret = true;
221         }
222
223         if (m_drawingTree->countChildren()) {
224 #ifdef ANIM_DEBUG
225             XLOGC("drawing tree %p with animation time offset of %f, locked %d",
226                   m_drawingTree, m_animationOffset, m_isAnimating);
227 #endif
228             LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
229             laTree->computeTexturesAmount(texturesResultPtr);
230             m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset);
231             if (!m_isAnimating)
232                 m_animationOffset = 0;
233             ret |= m_isAnimating;
234         } else if (!m_paintingTree) {
235             m_animationOffset = 0;
236             m_isAnimating = false;
237         }
238         XLOG("drawing tree %p", m_drawingTree);
239         ret |= m_drawingTree->drawGL(viewRect, visibleRect, scale);
240     } else if (m_paintingTree && m_paintingTree->state()) {
241         // Dont have a drawing tree, draw white background
242         Color defaultBackground = Color::white;
243         m_paintingTree->state()->drawBackground(defaultBackground);
244     }
245
246     m_lastFrameTime = currentTime;
247
248     if (m_paintingTree) {
249         XLOG("still have painting tree %p", m_paintingTree);
250         return true;
251     }
252
253     return ret;
254 }
255
256 int TreeManager::getTotalPaintedSurfaceCount()
257 {
258     return TilesManager::instance()->getPaintedSurfaceCount();
259 }
260
261 // draw for base tile - called on TextureGeneration thread
262 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
263 {
264     BaseLayerAndroid* paintingTree = 0;
265     m_paintSwapLock.lock();
266     if (m_paintingTree)
267         paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
268     else
269         paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
270     SkSafeRef(paintingTree);
271     m_paintSwapLock.unlock();
272
273     if (!paintingTree)
274         return;
275
276
277     paintingTree->drawCanvas(canvas);
278
279     if (drawLayers && paintingTree->countChildren()) {
280         // draw the layers onto the canvas as well
281         Layer* layers = paintingTree->getChild(0);
282         static_cast<LayerAndroid*>(layers)->drawCanvas(canvas);
283     }
284
285     SkSafeUnref(paintingTree);
286 }
287
288 int TreeManager::baseContentWidth()
289 {
290     if (m_paintingTree) {
291         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->width();
292     } else if (m_drawingTree) {
293         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->width();
294     }
295     return 0;
296 }
297
298 int TreeManager::baseContentHeight()
299 {
300     if (m_paintingTree) {
301         return static_cast<BaseLayerAndroid*>(m_paintingTree)->content()->height();
302     } else if (m_drawingTree) {
303         return static_cast<BaseLayerAndroid*>(m_drawingTree)->content()->height();
304     }
305     return 0;
306 }
307
308 } // namespace WebCore