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_paintingTree->countChildren()) {
190 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
191 laTree->computeTexturesAmount(texturesResultPtr);
193 if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
194 XLOG("have painting tree %p ready, swapping!", m_paintingTree);
197 if (buffersSwappedPtr)
198 *buffersSwappedPtr = true;
200 } else if (m_drawingTree) {
201 XLOG("preparing drawing tree %p", m_drawingTree);
202 ret |= m_drawingTree->prepare(currentTime, viewRect,
204 if (m_drawingTree->countChildren()) {
205 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
206 laTree->computeTexturesAmount(texturesResultPtr);
210 if (!m_isAnimating) {
211 m_animationOffset += currentTime - m_lastFrameTime;
213 XLOGC("adding to %f", m_animationOffset);
218 bool drawingReady = didTreeSwap || m_drawingTree->isReady();
220 if (drawingReady || m_fastSwapMode)
221 m_drawingTree->swapTiles();
224 // exit fast swap mode, as content is up to date
225 m_fastSwapMode = false;
227 // drawing isn't ready, must redraw
231 if (m_drawingTree->countChildren()) {
233 XLOGC("drawing tree %p with animation time offset of %f, locked %d",
234 m_drawingTree, m_animationOffset, m_isAnimating);
236 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
237 m_isAnimating = laTree->evaluateAnimations(currentTime - m_animationOffset);
239 m_animationOffset = 0;
240 ret |= m_isAnimating;
241 } else if (!m_paintingTree) {
242 m_animationOffset = 0;
243 m_isAnimating = false;
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);
253 m_lastFrameTime = currentTime;
255 if (m_paintingTree) {
256 XLOG("still have painting tree %p", m_paintingTree);
263 int TreeManager::getTotalPaintedSurfaceCount()
265 return TilesManager::instance()->getPaintedSurfaceCount();
268 // draw for base tile - called on TextureGeneration thread
269 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
271 BaseLayerAndroid* paintingTree = 0;
272 m_paintSwapLock.lock();
274 paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
276 paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
277 SkSafeRef(paintingTree);
278 m_paintSwapLock.unlock();
284 paintingTree->drawCanvas(canvas);
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);
292 SkSafeUnref(paintingTree);
295 int TreeManager::baseContentWidth()
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();
305 int TreeManager::baseContentHeight()
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();
315 } // namespace WebCore