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 "ScrollableLayerAndroid.h"
32 #include "TilesManager.h"
34 #include <cutils/log.h>
35 #include <wtf/CurrentTime.h>
36 #include <wtf/text/CString.h>
39 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
44 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TreeManager", __VA_ARGS__)
55 TreeManager::TreeManager()
59 , m_fastSwapMode(false)
63 TreeManager::~TreeManager()
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()
74 // swap can't be called unless painting just finished
75 ASSERT(m_paintingTree);
77 android::Mutex::Autolock lock(m_paintSwapLock);
79 XLOG("SWAPPING, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
81 // if we have a drawing tree, discard it since the painting tree is done
83 XLOG("destroying drawing tree %p", m_drawingTree);
84 m_drawingTree->setIsDrawing(false);
85 SkSafeUnref(m_drawingTree);
88 // painting tree becomes the drawing tree
89 XLOG("drawing tree %p", m_paintingTree);
90 m_paintingTree->setIsDrawing(true);
93 // start painting with the queued tree
94 XLOG("now painting tree %p", m_queuedTree);
95 m_queuedTree->setIsPainting(m_paintingTree);
97 m_drawingTree = m_paintingTree;
98 m_paintingTree = m_queuedTree;
101 TilesManager::instance()->paintedSurfacesCleanup();
103 XLOG("SWAPPING COMPLETE, D %p, P %p, Q %p", m_drawingTree, m_paintingTree, m_queuedTree);
106 // clear all of the content in the three trees held by the tree manager
107 void TreeManager::clearTrees()
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;
113 oldState = m_drawingTree->state();
114 m_drawingTree->setIsDrawing(false);
116 if (m_paintingTree) {
117 oldState = m_paintingTree->state();
118 m_paintingTree->setIsDrawing(false);
121 XLOG("TreeManager %p removing PS from state %p", this, oldState);
122 TilesManager::instance()->paintedSurfacesCleanup(oldState);
124 SkSafeUnref(m_drawingTree);
126 SkSafeUnref(m_paintingTree);
128 SkSafeUnref(m_queuedTree);
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)
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);
141 // can't have a queued tree unless have a painting tree too
142 ASSERT(m_paintingTree || !m_queuedTree);
146 android::Mutex::Autolock lock(m_paintSwapLock);
148 if (!newTree || brandNew) {
151 m_paintingTree = newTree;
152 m_paintingTree->setIsPainting(m_drawingTree);
157 if (m_queuedTree || m_paintingTree) {
158 // currently painting, so defer this new tree
160 // have a queued tree, copy over invals so the regions are
161 // eventually repainted
162 m_queuedTree->mergeInvalsInto(newTree);
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);
169 SkSafeUnref(m_queuedTree);
170 m_queuedTree = newTree;
174 // don't have painting tree, paint this one!
175 m_paintingTree = newTree;
176 m_paintingTree->setIsPainting(m_drawingTree);
179 void TreeManager::updateScrollableLayerInTree(Layer* tree, int layerId, int x, int y)
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);
189 void TreeManager::updateScrollableLayer(int layerId, int x, int y)
191 updateScrollableLayerInTree(m_queuedTree, layerId, x, y);
192 updateScrollableLayerInTree(m_paintingTree, layerId, x, y);
193 updateScrollableLayerInTree(m_drawingTree, layerId, x, y);
196 bool TreeManager::drawGL(double currentTime, IntRect& viewRect,
197 SkRect& visibleRect, float scale,
198 bool enterFastSwapMode, bool* treesSwappedPtr, bool* newTreeHasAnimPtr,
199 TexturesResult* texturesResultPtr)
201 m_fastSwapMode |= enterFastSwapMode;
203 XLOG("drawGL, D %p, P %p, Q %p, fastSwap %d",
204 m_drawingTree, m_paintingTree, m_queuedTree, m_fastSwapMode);
207 bool didTreeSwap = false;
208 if (m_paintingTree) {
209 ret |= m_paintingTree->prepare(currentTime, viewRect,
211 LayerAndroid* laTree = 0;
213 if (m_paintingTree->countChildren()) {
214 laTree = static_cast<LayerAndroid*>(m_paintingTree->getChild(0));
215 laTree->computeTexturesAmount(texturesResultPtr);
217 if (/*!m_fastSwapMode && */ m_paintingTree->isReady()) {
218 XLOG("have painting tree %p ready, swapping!", m_paintingTree);
222 *treesSwappedPtr = true;
223 if (laTree && newTreeHasAnimPtr)
224 *newTreeHasAnimPtr = laTree->hasAnimations();
226 } else if (m_drawingTree) {
227 XLOG("preparing drawing tree %p", m_drawingTree);
228 ret |= m_drawingTree->prepare(currentTime, viewRect,
230 if (m_drawingTree->countChildren()) {
231 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
232 laTree->computeTexturesAmount(texturesResultPtr);
238 bool drawingReady = didTreeSwap || m_drawingTree->isReady();
240 if (didTreeSwap || m_fastSwapMode || (drawingReady && !m_paintingTree))
241 m_drawingTree->swapTiles();
244 // exit fast swap mode, as content is up to date
245 m_fastSwapMode = false;
247 // drawing isn't ready, must redraw
251 if (m_drawingTree->countChildren()) {
252 LayerAndroid* laTree = static_cast<LayerAndroid*>(m_drawingTree->getChild(0));
253 ret |= laTree->evaluateAnimations(currentTime);
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);
263 if (m_paintingTree) {
264 XLOG("still have painting tree %p", m_paintingTree);
271 int TreeManager::getTotalPaintedSurfaceCount()
273 return TilesManager::instance()->getPaintedSurfaceCount();
276 // draw for base tile - called on TextureGeneration thread
277 void TreeManager::drawCanvas(SkCanvas* canvas, bool drawLayers)
279 BaseLayerAndroid* paintingTree = 0;
280 m_paintSwapLock.lock();
282 paintingTree = static_cast<BaseLayerAndroid*>(m_paintingTree);
284 paintingTree = static_cast<BaseLayerAndroid*>(m_drawingTree);
285 SkSafeRef(paintingTree);
286 m_paintSwapLock.unlock();
292 paintingTree->drawCanvas(canvas);
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);
300 SkSafeUnref(paintingTree);
303 int TreeManager::baseContentWidth()
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();
313 int TreeManager::baseContentHeight()
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();
323 } // namespace WebCore