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 "SurfaceCollectionManager.h"
39#include <utils/threads.h>
40
41// Performance measurements probe
42// To use it, enable the visual indicators in debug mode.
43// turning off the visual indicators will flush the measures.
44// #define MEASURES_PERF
45#define MAX_MEASURES_PERF 2000
46
47// Prefetch and render 1 tiles ahead of the scroll
48// TODO: We should either dynamically change the outer bound by detecting the
49// HW limit or save further in the GPU memory consumption.
50#define TILE_PREFETCH_DISTANCE 1
51
52namespace WebCore {
53
54class BaseLayerAndroid;
55class LayerAndroid;
56class ScrollableLayerAndroid;
57class TexturesResult;
58
59/////////////////////////////////////////////////////////////////////////////////
60// GL Architecture
61/////////////////////////////////////////////////////////////////////////////////
62//
63// To draw things, WebView use a tree of layers. The root of that tree is a
64// BaseLayerAndroid, which may have numerous LayerAndroid over it. The content
65// of those layers are SkPicture, the content of the BaseLayer is an PictureSet.
66//
67// When drawing, we therefore have one large "surface" that is the BaseLayer,
68// and (possibly) additional surfaces (usually smaller), which are the
69// LayerAndroids. The BaseLayer usually corresponds to the normal web page
70// content, the Layers are used for some parts such as specific divs (e.g. fixed
71// position divs, or elements using CSS3D transforms, or containing video,
72// plugins, etc.).
73//
74// *** NOTE: The GL drawing architecture only paints the BaseLayer for now.
75//
76// The rendering model is to use tiles to display the BaseLayer (as obviously a
77// BaseLayer's area can be arbitrarly large). The idea is to compute a set of
78// tiles covering the visibleContentRect's area, paint those tiles using the webview's
79// content (i.e. the BaseLayer's PictureSet), then display those tiles.
80// We check which tile we should use at every frame.
81//
82// Overview
83// ---------
84//
85// The tiles are grouped into a TiledPage -- basically a map of tiles covering
86// the BaseLayer's surface. When drawing, we ask the TiledPage to prepare()
87// itself then draw itself on screen. The prepare() function is the one
88// that schedules tiles to be painted -- i.e. the subset of tiles that intersect
89// with the current visibleContentRect. When they are ready, we can display
90// the TiledPage.
91//
92// Note that BaseLayerAndroid::drawGL() will return true to the java side if
93// there is a need to be called again (i.e. if we do not have up to date
94// textures or a transition is going on).
95//
96// Tiles are implemented as a Tile. It knows how to paint itself with the
97// PictureSet, and to display itself. A GL texture is usually associated to it.
98//
99// We also works with two TiledPages -- one to display the page at the
100// current scale factor, and another we use to paint the page at a different
101// scale factor. I.e. when we zoom, we use TiledPage A, with its tiles scaled
102// accordingly (and therefore possible loss of quality): this is fast as it's
103// purely a hardware operation. When the user is done zooming, we ask for
104// TiledPage B to be painted at the new scale factor, covering the
105// visibleContentRect's area. When B is ready, we swap it with A.
106//
107// Texture allocation
108// ------------------
109//
110// Obviously we cannot have every Tile having a GL texture -- we need to
111// get the GL textures from an existing pool, and reuse them.
112//
113// The way we do it is that when we call TiledPage::prepare(), we group the
114// tiles we need (i.e. in the visibleContentRect and dirty) into a TilesSet and call
115// Tile::reserveTexture() for each tile (which ensures there is a specific
116// GL textures backing the Tiles).
117//
118// reserveTexture() will ask the TilesManager for a texture. The allocation
119// mechanism goal is to (in order):
120// - prefers to allocate the same texture as the previous time
121// - prefers to allocate textures that are as far from the visibleContentRect as possible
122// - prefers to allocate textures that are used by different TiledPages
123//
124// Note that to compute the distance of each tile from the visibleContentRect, each time
125// we prepare() a TiledPage. Also during each prepare() we compute which tiles
126// are dirty based on the info we have received from webkit.
127//
128// Tile Invalidation
129// ------------------
130//
131// We do not want to redraw a tile if the tile is up-to-date. A tile is
132// considered to be dirty an in need of redrawing in the following cases
133//  - the tile has acquires a new texture
134//  - webkit invalidates all or part of the tiles contents
135//
136// To handle the case of webkit invalidation we store two ids (counters) of the
137// pictureSets in the tile.  The first id (A) represents the pictureSet used to
138// paint the tile and the second id (B) represents the pictureSet in which the
139// tile was invalidated by webkit. Thus, if A < B then tile is dirty.
140//
141// Since invalidates can occur faster than a full tiled page update, the tiled
142// page is protected by a 'lock' (m_baseLayerUpdate) that is set to true to
143// defer updates to the background layer, giving the foreground time to render
144// content instead of constantly flushing with invalidates. See
145// lockBaseLayerUpdate() & unlockBaseLayerUpdate().
146//
147// Painting scheduling
148// -------------------
149//
150// The next operation is to schedule this TilesSet to be painted
151// (TilesManager::schedulePaintForTilesSet()). TexturesGenerator
152// will get the TilesSet and ask the Tiles in it to be painted.
153//
154// Tile::paintBitmap() will paint the texture using the BaseLayer's
155// PictureSet (calling TiledPage::paintBaseLayerContent() which in turns
156// calls GLWebViewState::paintBaseLayerContent()).
157//
158// Note that TexturesGenerator is running in a separate thread, the textures
159// are shared using EGLImages (this is necessary to not slow down the rendering
160// speed -- updating GL textures in the main GL thread would slow things down).
161//
162/////////////////////////////////////////////////////////////////////////////////
163
164class GLWebViewState {
165public:
166    GLWebViewState();
167    ~GLWebViewState();
168
169    bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator,
170                      bool isPictureAfterFirstLayout);
171    void paintExtras();
172
173    GLExtras* glExtras() { return &m_glExtras; }
174
175    void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; }
176    bool isScrolling() { return m_isScrolling || m_isVisibleContentRectScrolling; }
177
178    bool setLayersRenderingMode(TexturesResult&);
179
180    int drawGL(IntRect& rect, SkRect& visibleContentRect, IntRect* invalRect,
181               IntRect& screenRect, int titleBarHeight,
182               IntRect& clip, float scale,
183               bool* collectionsSwappedPtr, bool* newCollectionHasAnimPtr,
184               bool shouldDraw);
185
186#ifdef MEASURES_PERF
187    void dumpMeasures();
188#endif
189
190    void addDirtyArea(const IntRect& rect);
191    void resetLayersDirtyArea();
192    void doFrameworkFullInval();
193    bool inUnclippedDraw() { return m_inUnclippedDraw; }
194
195    bool goingDown() { return m_goingDown; }
196    bool goingLeft() { return m_goingLeft; }
197
198    float scale() { return m_scale; }
199
200    // Currently, we only use 3 modes : kAllTextures, kClippedTextures and
201    // kSingleSurfaceRendering ( for every mode > kClippedTextures ) .
202    enum LayersRenderingMode {
203        kAllTextures              = 0, // all layers are drawn with textures fully covering them
204        kClippedTextures          = 1, // all layers are drawn, but their textures will be clipped
205        kScrollableAndFixedLayers = 2, // only scrollable and fixed layers will be drawn
206        kFixedLayers              = 3, // only fixed layers will be drawn
207        kSingleSurfaceRendering   = 4  // no layers will be drawn on separate textures
208                                       // -- everything is drawn on the base surface.
209    };
210
211    LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; }
212    bool isSingleSurfaceRenderingMode() { return m_layersRenderingMode == kSingleSurfaceRendering; }
213    void scrollLayer(int layerId, int x, int y);
214
215private:
216    void setVisibleContentRect(const SkRect& visibleContentRect, float scale);
217    double setupDrawing(const IntRect& invScreenRect, const SkRect& visibleContentRect,
218                        const IntRect& screenRect, int titleBarHeight,
219                        const IntRect& screenClip, float scale);
220    void showFrameInfo(const IntRect& rect, bool collectionsSwapped);
221    void clearRectWithColor(const IntRect& rect, float r, float g,
222                            float b, float a);
223    double m_prevDrawTime;
224
225    SkRect m_visibleContentRect;
226    IntRect m_frameworkLayersInval;
227    bool m_doFrameworkFullInval;
228    bool m_inUnclippedDraw;
229
230#ifdef MEASURES_PERF
231    unsigned int m_totalTimeCounter;
232    int m_timeCounter;
233    double m_delayTimes[MAX_MEASURES_PERF];
234    bool m_measurePerfs;
235#endif
236    GLExtras m_glExtras;
237
238    bool m_isScrolling;
239    bool m_isVisibleContentRectScrolling;
240    bool m_goingDown;
241    bool m_goingLeft;
242
243    float m_scale;
244
245    LayersRenderingMode m_layersRenderingMode;
246    SurfaceCollectionManager m_surfaceCollectionManager;
247};
248
249} // namespace WebCore
250
251#endif // USE(ACCELERATED_COMPOSITING)
252#endif // GLWebViewState_h
253