• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef GLWebViewState_h
27 #define GLWebViewState_h
28 
29 #if USE(ACCELERATED_COMPOSITING)
30 
31 #include "Color.h"
32 #include "DrawExtra.h"
33 #include "GLExtras.h"
34 #include "IntRect.h"
35 #include "SkCanvas.h"
36 #include "SkRect.h"
37 #include "SkRegion.h"
38 #include "TiledPage.h"
39 #include "ZoomManager.h"
40 #include <utils/threads.h>
41 
42 // Performance measurements probe
43 // To use it, enable the visual indicators in debug mode.
44 // turning off the visual indicators will flush the measures.
45 // #define MEASURES_PERF
46 #define MAX_MEASURES_PERF 2000
47 
48 // Prefetch and render 1 tiles ahead of the scroll
49 // TODO: We should either dynamically change the outer bound by detecting the
50 // HW limit or save further in the GPU memory consumption.
51 #define TILE_PREFETCH_DISTANCE 1
52 
53 // ratio of content to view required for prefetching to enable
54 #define TILE_PREFETCH_RATIO 1.2
55 
56 namespace WebCore {
57 
58 class BaseLayerAndroid;
59 class LayerAndroid;
60 
61 /////////////////////////////////////////////////////////////////////////////////
62 // GL Architecture
63 /////////////////////////////////////////////////////////////////////////////////
64 //
65 // To draw things, WebView use a tree of layers. The root of that tree is a
66 // BaseLayerAndroid, which may have numerous LayerAndroid over it. The content
67 // of those layers are SkPicture, the content of the BaseLayer is an PictureSet.
68 //
69 // When drawing, we therefore have one large "surface" that is the BaseLayer,
70 // and (possibly) additional surfaces (usually smaller), which are the
71 // LayerAndroids. The BaseLayer usually corresponds to the normal web page
72 // content, the Layers are used for some parts such as specific divs (e.g. fixed
73 // position divs, or elements using CSS3D transforms, or containing video,
74 // plugins, etc.).
75 //
76 // *** NOTE: The GL drawing architecture only paints the BaseLayer for now.
77 //
78 // The rendering model is to use tiles to display the BaseLayer (as obviously a
79 // BaseLayer's area can be arbitrarly large). The idea is to compute a set of
80 // tiles covering the viewport's area, paint those tiles using the webview's
81 // content (i.e. the BaseLayer's PictureSet), then display those tiles.
82 // We check which tile we should use at every frame.
83 //
84 // Overview
85 // ---------
86 //
87 // The tiles are grouped into a TiledPage -- basically a map of tiles covering
88 // the BaseLayer's surface. When drawing, we ask the TiledPage to prepare()
89 // itself then draw itself on screen. The prepare() function is the one
90 // that schedules tiles to be painted -- i.e. the subset of tiles that intersect
91 // with the current viewport. When they are ready, we can display
92 // the TiledPage.
93 //
94 // Note that BaseLayerAndroid::drawGL() will return true to the java side if
95 // there is a need to be called again (i.e. if we do not have up to date
96 // textures or a transition is going on).
97 //
98 // Tiles are implemented as a BaseTile. It knows how to paint itself with the
99 // PictureSet, and to display itself. A GL texture is usually associated to it.
100 //
101 // We also works with two TiledPages -- one to display the page at the
102 // current scale factor, and another we use to paint the page at a different
103 // scale factor. I.e. when we zoom, we use TiledPage A, with its tiles scaled
104 // accordingly (and therefore possible loss of quality): this is fast as it's
105 // purely a hardware operation. When the user is done zooming, we ask for
106 // TiledPage B to be painted at the new scale factor, covering the
107 // viewport's area. When B is ready, we swap it with A.
108 //
109 // Texture allocation
110 // ------------------
111 //
112 // Obviously we cannot have every BaseTile having a GL texture -- we need to
113 // get the GL textures from an existing pool, and reuse them.
114 //
115 // The way we do it is that when we call TiledPage::prepare(), we group the
116 // tiles we need (i.e. in the viewport and dirty) into a TilesSet and call
117 // BaseTile::reserveTexture() for each tile (which ensures there is a specific
118 // GL textures backing the BaseTiles).
119 //
120 // reserveTexture() will ask the TilesManager for a texture. The allocation
121 // mechanism goal is to (in order):
122 // - prefers to allocate the same texture as the previous time
123 // - prefers to allocate textures that are as far from the viewport as possible
124 // - prefers to allocate textures that are used by different TiledPages
125 //
126 // Note that to compute the distance of each tile from the viewport, each time
127 // we prepare() a TiledPage. Also during each prepare() we compute which tiles
128 // are dirty based on the info we have received from webkit.
129 //
130 // BaseTile Invalidation
131 // ------------------
132 //
133 // We do not want to redraw a tile if the tile is up-to-date. A tile is
134 // considered to be dirty an in need of redrawing in the following cases
135 //  - the tile has acquires a new texture
136 //  - webkit invalidates all or part of the tiles contents
137 //
138 // To handle the case of webkit invalidation we store two ids (counters) of the
139 // pictureSets in the tile.  The first id (A) represents the pictureSet used to
140 // paint the tile and the second id (B) represents the pictureSet in which the
141 // tile was invalidated by webkit. Thus, if A < B then tile is dirty.
142 //
143 // Since invalidates can occur faster than a full tiled page update, the tiled
144 // page is protected by a 'lock' (m_baseLayerUpdate) that is set to true to
145 // defer updates to the background layer, giving the foreground time to render
146 // content instead of constantly flushing with invalidates. See
147 // lockBaseLayerUpdate() & unlockBaseLayerUpdate().
148 //
149 // Painting scheduling
150 // -------------------
151 //
152 // The next operation is to schedule this TilesSet to be painted
153 // (TilesManager::schedulePaintForTilesSet()). TexturesGenerator
154 // will get the TilesSet and ask the BaseTiles in it to be painted.
155 //
156 // BaseTile::paintBitmap() will paint the texture using the BaseLayer's
157 // PictureSet (calling TiledPage::paintBaseLayerContent() which in turns
158 // calls GLWebViewState::paintBaseLayerContent()).
159 //
160 // Note that TexturesGenerator is running in a separate thread, the textures
161 // are shared using EGLImages (this is necessary to not slow down the rendering
162 // speed -- updating GL textures in the main GL thread would slow things down).
163 //
164 /////////////////////////////////////////////////////////////////////////////////
165 
166 class GLWebViewState {
167 public:
168     GLWebViewState(android::Mutex* globalButtonMutex);
169     ~GLWebViewState();
170 
zoomManager()171     ZoomManager* zoomManager() { return &m_zoomManager; }
futureViewport()172     const SkIRect& futureViewport() const { return m_futureViewportTileBounds; }
setFutureViewport(const SkIRect & viewport)173     void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; }
174 
175     unsigned int paintBaseLayerContent(SkCanvas* canvas);
176     void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator,
177                       bool isPictureAfterFirstLayout);
178     void paintExtras();
179 
glExtras()180     GLExtras* glExtras() { return &m_glExtras; }
181 
182     TiledPage* sibling(TiledPage* page);
183     TiledPage* frontPage();
184     TiledPage* backPage();
185     void swapPages();
186 
187     // dimensions of the current base layer
188     int baseContentWidth();
189     int baseContentHeight();
190 
191     void setViewport(SkRect& viewport, float scale);
192 
193     // a rect containing the coordinates of all tiles in the current viewport
viewportTileBounds()194     const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; }
195     // a rect containing the viewportTileBounds before there was a scale change
preZoomBounds()196     const SkIRect& preZoomBounds() const { return m_preZoomBounds; }
setPreZoomBounds(const SkIRect & bounds)197     void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; }
198 
currentPictureCounter()199     unsigned int currentPictureCounter() const { return m_currentPictureCounter; }
200 
lockBaseLayerUpdate()201     void lockBaseLayerUpdate() { m_baseLayerUpdate = false; }
202     void unlockBaseLayerUpdate();
203 
setIsScrolling(bool isScrolling)204     void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; }
isScrolling()205     bool isScrolling() { return m_isScrolling; }
206 
207     double setupDrawing(IntRect& rect, SkRect& viewport, IntRect& webViewRect,
208                 int titleBarHeight, IntRect& screenClip,
209                 float scale);
210 
211     bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
212                 IntRect& webViewRect, int titleBarHeight,
213                 IntRect& clip, float scale, bool* buffersSwappedPtr);
214 
215 #ifdef MEASURES_PERF
216     void dumpMeasures();
217 #endif
218 
219     void resetFrameworkInval();
220     void addDirtyArea(const IntRect& rect);
221     void resetLayersDirtyArea();
222 
goingDown()223     bool goingDown() { return m_goingDown; }
goingLeft()224     bool goingLeft() { return m_goingLeft; }
setDirection(bool goingDown,bool goingLeft)225     void setDirection(bool goingDown, bool goingLeft) {
226         m_goingDown = goingDown;
227         m_goingLeft = goingLeft;
228     }
229 
expandedTileBoundsX()230     int expandedTileBoundsX() { return m_expandedTileBoundsX; }
expandedTileBoundsY()231     int expandedTileBoundsY() { return m_expandedTileBoundsY; }
232 
scale()233     float scale() { return m_scale; }
234 
235 private:
236     void inval(const IntRect& rect); // caller must hold m_baseLayerLock
237     void invalRegion(const SkRegion& region);
238 
239     ZoomManager m_zoomManager;
240     android::Mutex m_tiledPageLock;
241     SkRect m_viewport;
242     SkIRect m_viewportTileBounds;
243     SkIRect m_futureViewportTileBounds;
244     SkIRect m_preZoomBounds;
245     android::Mutex m_baseLayerLock;
246     BaseLayerAndroid* m_paintingBaseLayer;
247     BaseLayerAndroid* m_currentBaseLayer;
248     LayerAndroid* m_currentBaseLayerRoot;
249 
250     unsigned int m_currentPictureCounter;
251     bool m_usePageA;
252     TiledPage* m_tiledPageA;
253     TiledPage* m_tiledPageB;
254     IntRect m_lastInval;
255     IntRect m_frameworkInval;
256     IntRect m_frameworkLayersInval;
257     android::Mutex* m_globalButtonMutex;
258 
259     bool m_baseLayerUpdate;
260     SkRegion m_invalidateRegion;
261 
262     Color m_backgroundColor;
263 
264 #ifdef MEASURES_PERF
265     unsigned int m_totalTimeCounter;
266     int m_timeCounter;
267     double m_delayTimes[MAX_MEASURES_PERF];
268     bool m_measurePerfs;
269 #endif
270     GLExtras m_glExtras;
271 
272     bool m_isScrolling;
273     bool m_goingDown;
274     bool m_goingLeft;
275 
276     int m_expandedTileBoundsX;
277     int m_expandedTileBoundsY;
278 
279     float m_scale;
280 };
281 
282 } // namespace WebCore
283 
284 #endif // USE(ACCELERATED_COMPOSITING)
285 #endif // GLWebViewState_h
286