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.
26 #ifndef GLWebViewState_h
27 #define GLWebViewState_h
29 #if USE(ACCELERATED_COMPOSITING)
32 #include "DrawExtra.h"
38 #include "TiledPage.h"
39 #include "TreeManager.h"
40 #include "ZoomManager.h"
41 #include <utils/threads.h>
43 // Performance measurements probe
44 // To use it, enable the visual indicators in debug mode.
45 // turning off the visual indicators will flush the measures.
46 // #define MEASURES_PERF
47 #define MAX_MEASURES_PERF 2000
49 // Prefetch and render 1 tiles ahead of the scroll
50 // TODO: We should either dynamically change the outer bound by detecting the
51 // HW limit or save further in the GPU memory consumption.
52 #define TILE_PREFETCH_DISTANCE 1
54 // ratio of content to view required for prefetching to enable
55 #define TILE_PREFETCH_RATIO 1.2
59 class BaseLayerAndroid;
61 class ScrollableLayerAndroid;
64 /////////////////////////////////////////////////////////////////////////////////
66 /////////////////////////////////////////////////////////////////////////////////
68 // To draw things, WebView use a tree of layers. The root of that tree is a
69 // BaseLayerAndroid, which may have numerous LayerAndroid over it. The content
70 // of those layers are SkPicture, the content of the BaseLayer is an PictureSet.
72 // When drawing, we therefore have one large "surface" that is the BaseLayer,
73 // and (possibly) additional surfaces (usually smaller), which are the
74 // LayerAndroids. The BaseLayer usually corresponds to the normal web page
75 // content, the Layers are used for some parts such as specific divs (e.g. fixed
76 // position divs, or elements using CSS3D transforms, or containing video,
79 // *** NOTE: The GL drawing architecture only paints the BaseLayer for now.
81 // The rendering model is to use tiles to display the BaseLayer (as obviously a
82 // BaseLayer's area can be arbitrarly large). The idea is to compute a set of
83 // tiles covering the viewport's area, paint those tiles using the webview's
84 // content (i.e. the BaseLayer's PictureSet), then display those tiles.
85 // We check which tile we should use at every frame.
90 // The tiles are grouped into a TiledPage -- basically a map of tiles covering
91 // the BaseLayer's surface. When drawing, we ask the TiledPage to prepare()
92 // itself then draw itself on screen. The prepare() function is the one
93 // that schedules tiles to be painted -- i.e. the subset of tiles that intersect
94 // with the current viewport. When they are ready, we can display
97 // Note that BaseLayerAndroid::drawGL() will return true to the java side if
98 // there is a need to be called again (i.e. if we do not have up to date
99 // textures or a transition is going on).
101 // Tiles are implemented as a BaseTile. It knows how to paint itself with the
102 // PictureSet, and to display itself. A GL texture is usually associated to it.
104 // We also works with two TiledPages -- one to display the page at the
105 // current scale factor, and another we use to paint the page at a different
106 // scale factor. I.e. when we zoom, we use TiledPage A, with its tiles scaled
107 // accordingly (and therefore possible loss of quality): this is fast as it's
108 // purely a hardware operation. When the user is done zooming, we ask for
109 // TiledPage B to be painted at the new scale factor, covering the
110 // viewport's area. When B is ready, we swap it with A.
112 // Texture allocation
113 // ------------------
115 // Obviously we cannot have every BaseTile having a GL texture -- we need to
116 // get the GL textures from an existing pool, and reuse them.
118 // The way we do it is that when we call TiledPage::prepare(), we group the
119 // tiles we need (i.e. in the viewport and dirty) into a TilesSet and call
120 // BaseTile::reserveTexture() for each tile (which ensures there is a specific
121 // GL textures backing the BaseTiles).
123 // reserveTexture() will ask the TilesManager for a texture. The allocation
124 // mechanism goal is to (in order):
125 // - prefers to allocate the same texture as the previous time
126 // - prefers to allocate textures that are as far from the viewport as possible
127 // - prefers to allocate textures that are used by different TiledPages
129 // Note that to compute the distance of each tile from the viewport, each time
130 // we prepare() a TiledPage. Also during each prepare() we compute which tiles
131 // are dirty based on the info we have received from webkit.
133 // BaseTile Invalidation
134 // ------------------
136 // We do not want to redraw a tile if the tile is up-to-date. A tile is
137 // considered to be dirty an in need of redrawing in the following cases
138 // - the tile has acquires a new texture
139 // - webkit invalidates all or part of the tiles contents
141 // To handle the case of webkit invalidation we store two ids (counters) of the
142 // pictureSets in the tile. The first id (A) represents the pictureSet used to
143 // paint the tile and the second id (B) represents the pictureSet in which the
144 // tile was invalidated by webkit. Thus, if A < B then tile is dirty.
146 // Since invalidates can occur faster than a full tiled page update, the tiled
147 // page is protected by a 'lock' (m_baseLayerUpdate) that is set to true to
148 // defer updates to the background layer, giving the foreground time to render
149 // content instead of constantly flushing with invalidates. See
150 // lockBaseLayerUpdate() & unlockBaseLayerUpdate().
152 // Painting scheduling
153 // -------------------
155 // The next operation is to schedule this TilesSet to be painted
156 // (TilesManager::schedulePaintForTilesSet()). TexturesGenerator
157 // will get the TilesSet and ask the BaseTiles in it to be painted.
159 // BaseTile::paintBitmap() will paint the texture using the BaseLayer's
160 // PictureSet (calling TiledPage::paintBaseLayerContent() which in turns
161 // calls GLWebViewState::paintBaseLayerContent()).
163 // Note that TexturesGenerator is running in a separate thread, the textures
164 // are shared using EGLImages (this is necessary to not slow down the rendering
165 // speed -- updating GL textures in the main GL thread would slow things down).
167 /////////////////////////////////////////////////////////////////////////////////
169 class GLWebViewState {
174 ZoomManager* zoomManager() { return &m_zoomManager; }
175 const SkIRect& futureViewport() const { return m_futureViewportTileBounds; }
176 void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; }
178 unsigned int paintBaseLayerContent(SkCanvas* canvas);
179 void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator,
180 bool isPictureAfterFirstLayout);
183 GLExtras* glExtras() { return &m_glExtras; }
185 TiledPage* sibling(TiledPage* page);
186 TiledPage* frontPage();
187 TiledPage* backPage();
190 // dimensions of the current base layer
191 int baseContentWidth();
192 int baseContentHeight();
194 void setViewport(SkRect& viewport, float scale);
196 // a rect containing the coordinates of all tiles in the current viewport
197 const SkIRect& viewportTileBounds() const { return m_viewportTileBounds; }
198 // a rect containing the viewportTileBounds before there was a scale change
199 const SkIRect& preZoomBounds() const { return m_preZoomBounds; }
200 void setPreZoomBounds(const SkIRect& bounds) { m_preZoomBounds = bounds; }
202 unsigned int currentPictureCounter() const { return m_currentPictureCounter; }
204 void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; }
205 bool isScrolling() { return m_isScrolling; }
207 void drawBackground(Color& backgroundColor);
208 double setupDrawing(IntRect& viewRect, SkRect& visibleRect,
209 IntRect& webViewRect, int titleBarHeight,
210 IntRect& screenClip, float scale);
212 bool setLayersRenderingMode(TexturesResult&);
215 bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
216 IntRect& webViewRect, int titleBarHeight,
217 IntRect& clip, float scale,
218 bool* treesSwappedPtr, bool* newTreeHasAnimPtr);
224 void resetFrameworkInval();
225 void addDirtyArea(const IntRect& rect);
226 void resetLayersDirtyArea();
228 bool goingDown() { return m_goingDown; }
229 bool goingLeft() { return m_goingLeft; }
230 void setDirection(bool goingDown, bool goingLeft) {
231 m_goingDown = goingDown;
232 m_goingLeft = goingLeft;
235 int expandedTileBoundsX() { return m_expandedTileBoundsX; }
236 int expandedTileBoundsY() { return m_expandedTileBoundsY; }
237 void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; }
239 float scale() { return m_scale; }
241 enum LayersRenderingMode {
242 kAllTextures = 0, // all layers are drawn with textures fully covering them
243 kClippedTextures = 1, // all layers are drawn, but their textures will be clipped
244 kScrollableAndFixedLayers = 2, // only scrollable and fixed layers will be drawn
245 kFixedLayers = 3, // only fixed layers will be drawn
246 kSingleSurfaceRendering = 4 // no layers will be drawn on separate textures
247 // -- everything is drawn on the base surface.
250 LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; }
251 void scrollLayer(int layerId, int x, int y);
253 void invalRegion(const SkRegion& region);
256 void inval(const IntRect& rect);
258 ZoomManager m_zoomManager;
259 android::Mutex m_tiledPageLock;
261 SkIRect m_viewportTileBounds;
262 SkIRect m_futureViewportTileBounds;
263 SkIRect m_preZoomBounds;
265 unsigned int m_currentPictureCounter;
267 TiledPage* m_tiledPageA;
268 TiledPage* m_tiledPageB;
270 IntRect m_frameworkInval;
271 IntRect m_frameworkLayersInval;
274 unsigned int m_totalTimeCounter;
276 double m_delayTimes[MAX_MEASURES_PERF];
285 int m_expandedTileBoundsX;
286 int m_expandedTileBoundsY;
291 LayersRenderingMode m_layersRenderingMode;
292 TreeManager m_treeManager;
295 } // namespace WebCore
297 #endif // USE(ACCELERATED_COMPOSITING)
298 #endif // GLWebViewState_h