OSDN Git Service

Merge "Prepare tiles in reverse draw order"
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / BaseLayerAndroid.cpp
1 /*
2  * Copyright 2010, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27 #include "BaseLayerAndroid.h"
28
29 #if USE(ACCELERATED_COMPOSITING)
30 #include "ClassTracker.h"
31 #include "GLUtils.h"
32 #include "ShaderProgram.h"
33 #include "SkCanvas.h"
34 #include "TilesManager.h"
35 #include <GLES2/gl2.h>
36 #include <wtf/CurrentTime.h>
37 #endif // USE(ACCELERATED_COMPOSITING)
38
39 #include <cutils/log.h>
40 #include <wtf/text/CString.h>
41
42 #undef XLOGC
43 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
44
45 #ifdef DEBUG
46
47 #undef XLOG
48 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseLayerAndroid", __VA_ARGS__)
49
50 #else
51
52 #undef XLOG
53 #define XLOG(...)
54
55 #endif // DEBUG
56
57 namespace WebCore {
58
59 using namespace android;
60
61 BaseLayerAndroid::BaseLayerAndroid()
62 #if USE(ACCELERATED_COMPOSITING)
63     : m_glWebViewState(0)
64     , m_color(Color::white)
65     , m_scrollState(NotScrolling)
66 #endif
67 {
68 #ifdef DEBUG_COUNT
69     ClassTracker::instance()->increment("BaseLayerAndroid");
70 #endif
71 }
72
73 BaseLayerAndroid::~BaseLayerAndroid()
74 {
75     m_content.clear();
76 #ifdef DEBUG_COUNT
77     ClassTracker::instance()->decrement("BaseLayerAndroid");
78 #endif
79 }
80
81 void BaseLayerAndroid::setContent(const PictureSet& src)
82 {
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);
90 #endif
91     m_content.set(src);
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());
96 }
97
98 void BaseLayerAndroid::setExtra(SkPicture& src)
99 {
100 #if USE(ACCELERATED_COMPOSITING)
101     android::Mutex::Autolock lock(m_drawLock);
102 #endif
103     m_extra.swap(src);
104 }
105
106 void BaseLayerAndroid::drawCanvas(SkCanvas* canvas)
107 {
108 #if USE(ACCELERATED_COMPOSITING)
109     android::Mutex::Autolock lock(m_drawLock);
110 #endif
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);
116 }
117
118 #if USE(ACCELERATED_COMPOSITING)
119 bool BaseLayerAndroid::drawBasePictureInGL(SkRect& viewport, float scale,
120                                            double currentTime, bool* buffersSwappedPtr)
121 {
122     ZoomManager* zoomManager = m_glWebViewState->zoomManager();
123
124     bool goingDown = m_glWebViewState->goingDown();
125     bool goingLeft = m_glWebViewState->goingLeft();
126
127     const SkIRect& viewportTileBounds = m_glWebViewState->viewportTileBounds();
128     XLOG("drawBasePicture, TX: %d, TY: %d scale %.2f", viewportTileBounds.fLeft,
129             viewportTileBounds.fTop, scale);
130
131     // Query the resulting state from the zoom manager
132     bool prepareNextTiledPage = zoomManager->needPrepareNextTiledPage();
133
134     // Display the current page
135     TiledPage* tiledPage = m_glWebViewState->frontPage();
136     TiledPage* nextTiledPage = m_glWebViewState->backPage();
137     tiledPage->setScale(zoomManager->currentScale());
138
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
145         // ignore dirtiness return value since while zooming we repaint regardless
146         nextTiledPage->updateTileDirtiness(viewportTileBounds);
147
148         nextTiledPage->prepare(goingDown, goingLeft, viewportTileBounds,
149                                TiledPage::VisibleBounds);
150         // Cancel pending paints for the foreground page
151         TilesManager::instance()->removePaintOperationsForPage(tiledPage, false);
152     }
153
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
160     }
161
162     float transparency = 1;
163     bool doZoomPageSwap = false;
164
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);
172     }
173
174     const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
175
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;
182
183     bool scrolling = m_scrollState != NotScrolling;
184     bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
185
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;
190     if (!zooming) {
191         TiledPage::SwapMethod swapMethod;
192         if (scrolling)
193             swapMethod = TiledPage::SwapWhateverIsReady;
194         else
195             swapMethod = TiledPage::SwapWholePage;
196
197         buffersSwapped = tiledPage->swapBuffersIfReady(preZoomBounds,
198                                                        zoomManager->currentScale(),
199                                                        swapMethod);
200
201         if (buffersSwappedPtr && buffersSwapped)
202             *buffersSwappedPtr = true;
203         if (buffersSwapped) {
204             if (m_scrollState == ScrollingFinishPaint) {
205                 m_scrollState = NotScrolling;
206                 scrolling = false;
207             }
208         }
209     }
210
211     if (doZoomPageSwap) {
212         zoomManager->setCurrentScale(scale);
213         m_glWebViewState->swapPages();
214         if (buffersSwappedPtr)
215             *buffersSwappedPtr = true;
216     }
217
218
219     bool needsRedraw = scrolling || zooming || !buffersSwapped;
220
221     // if we don't expect to redraw, unlock the invals
222     if (!needsRedraw)
223         m_glWebViewState->unlockBaseLayerUpdate();
224
225     // if applied invals mark tiles dirty, need to redraw
226     needsRedraw |= tiledPage->updateTileDirtiness(preZoomBounds);
227
228     if (needsRedraw) {
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();
232         if (!zooming)
233             tiledPage->prepare(goingDown, goingLeft, preZoomBounds,
234                                TiledPage::ExpandedBounds);
235     }
236
237     XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d",
238          scrolling, zooming, buffersSwapped, needsRedraw);
239
240     tiledPage->draw(transparency, preZoomBounds);
241
242     m_glWebViewState->paintExtras();
243     return needsRedraw;
244 }
245 #endif // USE(ACCELERATED_COMPOSITING)
246
247 bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
248                               IntRect& viewRect, SkRect& visibleRect, float scale,
249                               bool* buffersSwappedPtr)
250 {
251     bool needsRedraw = false;
252 #if USE(ACCELERATED_COMPOSITING)
253
254     needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
255                                       buffersSwappedPtr);
256
257     if (!needsRedraw)
258         m_glWebViewState->resetFrameworkInval();
259
260     if (compositedRoot) {
261         TransformationMatrix ident;
262
263         bool animsRunning = compositedRoot->evaluateAnimations();
264         if (animsRunning)
265             needsRedraw = true;
266
267         compositedRoot->updateFixedLayersPositions(visibleRect);
268         FloatRect clip(0, 0, viewRect.width(), viewRect.height());
269         compositedRoot->updateGLPositionsAndScale(
270             ident, clip, 1, m_glWebViewState->zoomManager()->layersScale());
271         SkMatrix matrix;
272         matrix.setTranslate(viewRect.x(), viewRect.y());
273
274 #ifdef DEBUG
275         compositedRoot->showLayer(0);
276         XLOG("We have %d layers, %d textured",
277               compositedRoot->nbLayers(),
278               compositedRoot->nbTexturedLayers());
279 #endif
280
281         // Clean up GL textures for video layer.
282         TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
283
284         compositedRoot->prepare(m_glWebViewState);
285         if (compositedRoot->drawGL(m_glWebViewState, matrix))
286             needsRedraw = true;
287         else if (!animsRunning)
288             m_glWebViewState->resetLayersDirtyArea();
289
290     }
291
292     m_previousVisible = visibleRect;
293
294 #endif // USE(ACCELERATED_COMPOSITING)
295 #ifdef DEBUG
296     ClassTracker::instance()->show();
297 #endif
298     return needsRedraw;
299 }
300
301 } // namespace WebCore