2 * Copyright 2010, 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 "BaseLayerAndroid.h"
29 #if USE(ACCELERATED_COMPOSITING)
30 #include "ClassTracker.h"
32 #include "ShaderProgram.h"
34 #include "TilesManager.h"
35 #include <GLES2/gl2.h>
36 #include <wtf/CurrentTime.h>
37 #endif // USE(ACCELERATED_COMPOSITING)
39 #include <cutils/log.h>
40 #include <wtf/text/CString.h>
43 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
48 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
59 using namespace android;
61 BaseLayerAndroid::BaseLayerAndroid()
62 #if USE(ACCELERATED_COMPOSITING)
64 , m_color(Color::white)
65 , m_scrollState(NotScrolling)
69 ClassTracker::instance()->increment("BaseLayerAndroid");
73 BaseLayerAndroid::~BaseLayerAndroid()
77 ClassTracker::instance()->decrement("BaseLayerAndroid");
81 void BaseLayerAndroid::setContent(const PictureSet& src)
83 #if USE(ACCELERATED_COMPOSITING)
84 // FIXME: We lock here because we do not want
85 // to paint and change the m_content concurrently.
86 // We should instead refactor PictureSet to use
87 // an atomic refcounting scheme and use atomic operations
88 // to swap PictureSets.
89 android::Mutex::Autolock lock(m_drawLock);
92 // FIXME: We cannot set the size of the base layer because it will screw up
93 // the matrix used. We need to fix matrix computation for the base layer
94 // and then we can set the size.
95 // setSize(src.width(), src.height());
98 void BaseLayerAndroid::setExtra(SkPicture& src)
100 #if USE(ACCELERATED_COMPOSITING)
101 android::Mutex::Autolock lock(m_drawLock);
106 void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
108 #if USE(ACCELERATED_COMPOSITING)
109 android::Mutex::Autolock lock(m_drawLock);
111 if (!m_content.isEmpty())
112 m_content.draw(canvas);
113 // TODO : replace with !m_extra.isEmpty() once such a call exists
114 if (m_extra.width() > 0)
115 m_extra.draw(canvas);
118 #if USE(ACCELERATED_COMPOSITING)
119 bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
120 double currentTime, bool* buffersSwappedPtr)
122 ZoomManager* zoomManager = m_glWebViewState->zoomManager();
124 bool goingDown = m_glWebViewState->goingDown();
125 bool goingLeft = m_glWebViewState->goingLeft();
127 const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
128 XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft,
129 viewportTileBounds.fTop, scale);
131 // Query the resulting state from the zoom manager
132 bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();
134 // Display the current page
135 TiledPage* tiledPage = m_glWebViewState->frontPage();
136 TiledPage* nextTiledPage = m_glWebViewState->backPage();
137 tiledPage->setScale(zoomManager->currentScale());
139 // Let's prepare the page if needed so that it will start painting
140 if (prepareNextTiledPage) {
141 nextTiledPage->setScale(scale);
142 m_glWebViewState->setFutureViewport(viewportTileBounds);
143 m_glWebViewState->lockBaseLayerUpdate();
145 // ignore dirtiness return value since while zooming we repaint regardless
146 nextTiledPage->updateTileDirtiness(viewportTileBounds);
148 nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
149 TiledPage::VisibleBounds);
150 // Cancel pending paints for the foreground page
151 TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
154 // If we fired a request, let's check if it's ready to use
155 if (zoomManager->didFireRequest()) {
156 if (nextTiledPage->swapBuffersIfReady(viewportTileBounds,
157 zoomManager->futureScale(),
158 TiledPage::SwapWholePage))
159 zoomManager->setReceivedRequest(); // transition to received request state
162 float transparency = 1;
163 bool doZoomPageSwap = false;
165 // If the page is ready, display it. We do a short transition between
166 // the two pages (current one and future one with the new scale factor)
167 if (zoomManager->didReceivedRequest()) {
168 float nextTiledPageTransparency = 1;
169 zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
170 &nextTiledPageTransparency, &transparency);
171 nextTiledPage->draw(nextTiledPageTransparency, viewportTileBounds);
174 const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
176 // update scrolling state machine by querying glwebviewstate - note that the
177 // NotScrolling state is only set below
178 if (m_glWebViewState->isScrolling())
179 m_scrollState = Scrolling;
180 else if (m_scrollState == Scrolling)
181 m_scrollState = ScrollingFinishPaint;
183 bool scrolling = m_scrollState != NotScrolling;
184 bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
186 // When we aren't zooming, we should TRY and swap tile buffers if they're
187 // ready. When scrolling, we swap whatever's ready. Otherwise, buffer until
188 // the entire page is ready and then swap.
189 bool buffersSwapped = false;
191 TiledPage::SwapMethod swapMethod;
193 swapMethod = TiledPage::SwapWhateverIsReady;
195 swapMethod = TiledPage::SwapWholePage;
197 buffersSwapped = tiledPage->swapBuffersIfReady(preZoomBounds,
198 zoomManager->currentScale(),
201 if (buffersSwappedPtr && buffersSwapped)
202 *buffersSwappedPtr = true;
203 if (buffersSwapped) {
204 if (m_scrollState == ScrollingFinishPaint) {
205 m_scrollState = NotScrolling;
211 if (doZoomPageSwap) {
212 zoomManager->setCurrentScale(scale);
213 m_glWebViewState->swapPages();
214 if (buffersSwappedPtr)
215 *buffersSwappedPtr = true;
219 bool needsRedraw = scrolling || zooming || !buffersSwapped;
221 // if we don't expect to redraw, unlock the invals
223 m_glWebViewState->unlockBaseLayerUpdate();
225 // if applied invals mark tiles dirty, need to redraw
226 needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds);
229 // lock and paint what's needed unless we're zooming, since the new
230 // tiles won't be relevant soon anyway
231 m_glWebViewState->lockBaseLayerUpdate();
233 tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
234 TiledPage::ExpandedBounds);
237 XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d",
238 scrolling, zooming, buffersSwapped, needsRedraw);
240 tiledPage->draw(transparency, preZoomBounds);
242 m_glWebViewState->paintExtras();
245 #endif // USE(ACCELERATED_COMPOSITING)
247 bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
248 IntRect& viewRect, SkRect& visibleRect, float scale,
249 bool* buffersSwappedPtr)
251 bool needsRedraw = false;
252 #if USE(ACCELERATED_COMPOSITING)
254 needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
258 m_glWebViewState->resetFrameworkInval();
260 if (compositedRoot) {
261 TransformationMatrix ident;
263 bool animsRunning = compositedRoot->evaluateAnimations();
267 compositedRoot->updateFixedLayersPositions(visibleRect);
268 FloatRect clip(0, 0, viewRect.width(), viewRect.height());
269 compositedRoot->updateGLPositionsAndScale(
270 ident, clip, 1, m_glWebViewState->zoomManager()->layersScale());
272 matrix.setTranslate(viewRect.x(), viewRect.y());
275 compositedRoot->showLayer(0);
276 XLOG("We have %d layers, %d textured",
277 compositedRoot->nbLayers(),
278 compositedRoot->nbTexturedLayers());
281 // Clean up GL textures for video layer.
282 TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
284 if (compositedRoot->drawGL(m_glWebViewState, matrix))
286 else if (!animsRunning)
287 m_glWebViewState->resetLayersDirtyArea();
291 m_previousVisible = visibleRect;
293 #endif // USE(ACCELERATED_COMPOSITING)
295 ClassTracker::instance()->show();
300 } // namespace WebCore