OSDN Git Service

Merge "The CPU code path for uploading the textures"
[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         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);
149     }
150
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
157     }
158
159     float transparency = 1;
160     bool doZoomPageSwap = false;
161
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);
169     }
170
171     const SkIRect& preZoomBounds = m_glWebViewState->preZoomBounds();
172
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;
179
180     bool scrolling = m_scrollState != NotScrolling;
181     bool zooming = ZoomManager::kNoScaleRequest != zoomManager->scaleRequestState();
182
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;
187     if (!zooming) {
188         TiledPage::SwapMethod swapMethod;
189         if (scrolling)
190             swapMethod = TiledPage::SwapWhateverIsReady;
191         else
192             swapMethod = TiledPage::SwapWholePage;
193
194         buffersSwapped = tiledPage->swapBuffersIfReady(preZoomBounds,
195                                                        zoomManager->currentScale(),
196                                                        swapMethod);
197
198         if (buffersSwappedPtr && buffersSwapped)
199             *buffersSwappedPtr = true;
200         if (buffersSwapped) {
201             if (m_scrollState == ScrollingFinishPaint) {
202                 m_scrollState = NotScrolling;
203                 scrolling = false;
204             }
205         }
206     }
207
208     if (doZoomPageSwap) {
209         zoomManager->setCurrentScale(scale);
210         m_glWebViewState->swapPages();
211         if (buffersSwappedPtr)
212             *buffersSwappedPtr = true;
213     }
214
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;
218     if (needsRedraw)
219         m_glWebViewState->lockBaseLayerUpdate();
220     else
221         m_glWebViewState->unlockBaseLayerUpdate();
222
223     XLOG("scrolling %d, zooming %d, buffersSwapped %d, needsRedraw %d",
224          scrolling, zooming, buffersSwapped, needsRedraw);
225
226     tiledPage->updateTileState(preZoomBounds);
227
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);
233
234     tiledPage->draw(transparency, preZoomBounds);
235
236     m_glWebViewState->paintExtras();
237     return needsRedraw;
238 }
239 #endif // USE(ACCELERATED_COMPOSITING)
240
241 bool BaseLayerAndroid::drawGL(double currentTime, LayerAndroid* compositedRoot,
242                               IntRect& viewRect, SkRect& visibleRect, float scale,
243                               bool* buffersSwappedPtr)
244 {
245     bool needsRedraw = false;
246 #if USE(ACCELERATED_COMPOSITING)
247
248     needsRedraw = drawBasePictureInGL(visibleRect, scale, currentTime,
249                                       buffersSwappedPtr);
250
251     if (!needsRedraw)
252         m_glWebViewState->resetFrameworkInval();
253
254     if (compositedRoot) {
255         TransformationMatrix ident;
256
257         bool animsRunning = compositedRoot->evaluateAnimations();
258         if (animsRunning)
259             needsRedraw = true;
260
261         compositedRoot->updateFixedLayersPositions(visibleRect);
262         FloatRect clip(0, 0, viewRect.width(), viewRect.height());
263         compositedRoot->updateGLPositions(ident, clip, 1);
264         SkMatrix matrix;
265         matrix.setTranslate(viewRect.x(), viewRect.y());
266
267         // get the scale factor from the zoom manager
268         compositedRoot->setScale(m_glWebViewState->zoomManager()->layersScale());
269
270 #ifdef DEBUG
271         compositedRoot->showLayer(0);
272         XLOG("We have %d layers, %d textured",
273               compositedRoot->nbLayers(),
274               compositedRoot->nbTexturedLayers());
275 #endif
276
277         // Clean up GL textures for video layer.
278         TilesManager::instance()->videoLayerManager()->deleteUnusedTextures();
279
280         if (compositedRoot->drawGL(m_glWebViewState, matrix))
281             needsRedraw = true;
282         else if (!animsRunning)
283             m_glWebViewState->resetLayersDirtyArea();
284
285     }
286
287     m_previousVisible = visibleRect;
288
289 #endif // USE(ACCELERATED_COMPOSITING)
290 #ifdef DEBUG
291     ClassTracker::instance()->show();
292 #endif
293     return needsRedraw;
294 }
295
296 } // namespace WebCore