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