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();
144 nextTiledPage->updateTileState(viewportTileBounds);
145 nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
146 TiledPage::VisibleBounds);
147 // Cancel pending paints for the foreground page
148 TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
151 // If we fired a request, let's check if it's ready to use
152 if (zoomManager->didFireRequest()) {
153 if (nextTiledPage->swapBuffersIfReady(viewportTileBounds,
154 zoomManager->futureScale(),
155 TiledPage::SwapWholePage))
156 zoomManager->setReceivedRequest(); // transition to received request state
159 float transparency = 1;
160 bool doZoomPageSwap = false;
162 // If the page is ready, display it. We do a short transition between
163 // the two pages (current one and future one with the new scale factor)
164 if (zoomManager->didReceivedRequest()) {
165 float nextTiledPageTransparency = 1;
166 zoomManager->processTransition(currentTime, scale, &doZoomPageSwap,
167 &nextTiledPageTransparency, &transparency);
168 nextTiledPage->draw(nextTiledPageTransparency, viewportTileBounds);
171 const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
173 // update scrolling state machine by querying glwebviewstate - note that the
174 // NotScrolling state is only set below
175 if (m_glWebViewState->isScrolling())
176 m_scrollState = Scrolling;
177 else if (m_scrollState == Scrolling)
178 m_scrollState = ScrollingFinishPaint;
180 bool scrolling = m_scrollState != NotScrolling;
181 bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
183 // When we aren't zooming, we should TRY and swap tile buffers if they're
184 // ready. When scrolling, we swap whatever's ready. Otherwise, buffer until
185 // the entire page is ready and then swap.
186 bool buffersSwapped = false;
188 TiledPage::SwapMethod swapMethod;
190 swapMethod = TiledPage::SwapWhateverIsReady;
192 swapMethod = TiledPage::SwapWholePage;
194 buffersSwapped = tiledPage->swapBuffersIfReady(preZoomBounds,
195 zoomManager->currentScale(),
198 if (buffersSwappedPtr && buffersSwapped)
199 *buffersSwappedPtr = true;
200 if (buffersSwapped) {
201 if (m_scrollState == ScrollingFinishPaint) {
202 m_scrollState = NotScrolling;
208 if (doZoomPageSwap) {
209 zoomManager->setCurrentScale(scale);
210 m_glWebViewState->swapPages();
211 if (buffersSwappedPtr)
212 *buffersSwappedPtr = true;
215 // If stuff is happening such that we need a redraw, lock updates to the
216 // base layer, and only then start painting.
217 bool needsRedraw = scrolling || zooming || !buffersSwapped;
219 m_glWebViewState->lockBaseLayerUpdate();
221 m_glWebViewState->unlockBaseLayerUpdate();
223 XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d",
224 scrolling, zooming, buffersSwapped, needsRedraw);
226 tiledPage->updateTileState(preZoomBounds);
228 // Only paint new textures if the base layer has been locked, but not if
229 // we're zooming since the new tiles won't be relevant soon anyway
230 if (needsRedraw && !zooming)
231 tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
232 TiledPage::ExpandedBounds);
234 tiledPage->draw(transparency, preZoomBounds);
236 m_glWebViewState->paintExtras();
239 #endif // USE(ACCELERATED_COMPOSITING)
241 bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
242 IntRect& viewRect, SkRect& visibleRect, float scale,
243 bool* buffersSwappedPtr)
245 bool needsRedraw = false;
246 #if USE(ACCELERATED_COMPOSITING)
248 needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
252 m_glWebViewState->resetFrameworkInval();
254 if (compositedRoot) {
255 TransformationMatrix ident;
257 bool animsRunning = compositedRoot->evaluateAnimations();
261 compositedRoot->updateFixedLayersPositions(visibleRect);
262 FloatRect clip(0, 0, viewRect.width(), viewRect.height());
263 compositedRoot->updateGLPositions(ident, clip, 1);
265 matrix.setTranslate(viewRect.x(), viewRect.y());
267 // get the scale factor from the zoom manager
268 compositedRoot->setScale(m_glWebViewState->zoomManager()->layersScale());
271 compositedRoot->showLayer(0);
272 XLOG("We have %d layers, %d textured",
273 compositedRoot->nbLayers(),
274 compositedRoot->nbTexturedLayers());
277 // Clean up GL textures for video layer.
278 TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
280 if (compositedRoot->drawGL(m_glWebViewState, matrix))
282 else if (!animsRunning)
283 m_glWebViewState->resetLayersDirtyArea();
287 m_previousVisible = visibleRect;
289 #endif // USE(ACCELERATED_COMPOSITING)
291 ClassTracker::instance()->show();
296 } // namespace WebCore