2 * Copyright 2011, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "TreeManager.h"
30 #include "BaseLayerAndroid.h"
31 #include "TilesManager.h"
33 #include <cutils/log.h>
34 #include <wtf/CurrentTime.h>
35 #include <wtf/text/CString.h>
38 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
43 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
54 TreeManager::TreeManager()
58 , m_fastSwapMode(false)
62 TreeManager::~TreeManager()
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()
73 // swap can't be called unless painting just finished
74 ASSERT(m_paintingTree);
76 android::Mutex::Autolock lock(m_paintSwapLock);
78 XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
80 // if we have a drawing tree, discard it since the painting tree is done
82 XLOG("destroying drawing tree %p", m_drawingTree);
83 m_drawingTree->setIsDrawing(false);
84 SkSafeUnref(m_drawingTree);
87 // painting tree becomes the drawing tree
88 XLOG("drawing tree %p", m_paintingTree);
89 m_paintingTree->setIsDrawing(true);
92 // start painting with the queued tree
93 XLOG("now painting tree %p", m_queuedTree);
94 m_queuedTree->setIsPainting(m_paintingTree);
96 m_drawingTree = m_paintingTree;
97 m_paintingTree = m_queuedTree;
100 TilesManager::instance()->paintedSurfacesCleanup();
102 XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
105 // clear all of the content in the three trees held by the tree manager
106 void TreeManager::clearTrees()
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;
112 oldState = m_drawingTree->state();
113 m_drawingTree->setIsDrawing(false);
115 if (m_paintingTree) {
116 oldState = m_paintingTree->state();
117 m_paintingTree->setIsDrawing(false);
120 XLOG("TreeManager %p removing PS from state %p", this, oldState);
121 TilesManager::instance()->paintedSurfacesCleanup(oldState);
123 SkSafeUnref(m_drawingTree);
125 SkSafeUnref(m_paintingTree);
127 SkSafeUnref(m_queuedTree);
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)
136 // can't have a queued tree unless have a painting tree too
137 ASSERT(m_paintingTree || !m_queuedTree);
141 android::Mutex::Autolock lock(m_paintSwapLock);
143 if (!newTree || brandNew) {
146 m_animationOffset = 0;
147 m_isAnimating = false;
148 m_lastFrameTime = WTF::currentTime();
150 m_paintingTree = newTree;
151 m_paintingTree->setIsPainting(m_drawingTree);
156 if (m_queuedTree || m_paintingTree) {
157 // currently painting, so defer this new tree
159 // have a queued tree, copy over invals so the regions are
160 // eventually repainted
161 m_queuedTree->mergeInvalsInto(newTree);
163 SkSafeUnref(m_queuedTree);
164 m_queuedTree = newTree;
168 // don't have painting tree, paint this one!
169 m_paintingTree = newTree;
170 m_paintingTree->setIsPainting(m_drawingTree);
173 bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
174 SkRect& visibleRect, float scale,
175 bool enterFastSwapMode, bool* buffersSwappedPtr,
176 TexturesResult* texturesResultPtr)
178 m_fastSwapMode |= enterFastSwapMode;
180 XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
181 m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);
184 bool didTreeSwap = false;
185 if (m_paintingTree) {
186 ret |= m_paintingTree->prepare(currentTime, viewRect,
189 if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
190 XLOG("have painting tree %p ready, swapping!", m_paintingTree);
193 if (buffersSwappedPtr)
194 *buffersSwappedPtr = true;
196 } else if (m_drawingTree) {
197 XLOG("preparing drawing tree %p", m_drawingTree);
198 ret |= m_drawingTree->prepare(currentTime, viewRect,
202 if (!m_isAnimating) {
203 m_animationOffset += currentTime - m_lastFrameTime;
205 XLOGC("adding to %f", m_animationOffset);
210 bool drawingReady = didTreeSwap || m_drawingTree->isReady();
212 if (didTreeSwap || m_fastSwapMode)
213 m_drawingTree->swapTiles();
216 // exit fast swap mode, as content is up to date
217 m_fastSwapMode = false;
219 // drawing isn't ready, must redraw
223 if (m_drawingTree->countChildren()) {
225 XLOGC("drawing tree %p with animation time offset of %f, locked %d",
226 m_drawingTree, m_animationOffset, m_isAnimating);
228 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
229 laTree->computeTexturesAmount(texturesResultPtr);
230 m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset);
232 m_animationOffset = 0;
233 ret |= m_isAnimating;
234 } else if (!m_paintingTree) {
235 m_animationOffset = 0;
236 m_isAnimating = false;
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);
246 m_lastFrameTime = currentTime;
248 if (m_paintingTree) {
249 XLOG("still have painting tree %p", m_paintingTree);
256 int TreeManager::getTotalPaintedSurfaceCount()
258 return TilesManager::instance()->getPaintedSurfaceCount();
261 // draw for base tile - called on TextureGeneration thread
262 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
264 BaseLayerAndroid* paintingTree = 0;
265 m_paintSwapLock.lock();
267 paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
269 paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
270 SkSafeRef(paintingTree);
271 m_paintSwapLock.unlock();
277 paintingTree->drawCanvas(canvas);
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);
285 SkSafeUnref(paintingTree);
288 int TreeManager::baseContentWidth()
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();
298 int TreeManager::baseContentHeight()
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();
308 } // namespace WebCore