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 "TreeManager.h" 40 #include "ZoomManager.h" 41 #include <utils/threads.h> 42 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 48 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 53 54 // ratio of content to view required for prefetching to enable 55 #define TILE_PREFETCH_RATIO 1.2 56 57 namespace WebCore { 58 59 class BaseLayerAndroid; 60 class LayerAndroid; 61 class ScrollableLayerAndroid; 62 class TexturesResult; 63 64 ///////////////////////////////////////////////////////////////////////////////// 65 // GL Architecture 66 ///////////////////////////////////////////////////////////////////////////////// 67 // 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. 71 // 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, 77 // plugins, etc.). 78 // 79 // *** NOTE: The GL drawing architecture only paints the BaseLayer for now. 80 // 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. 86 // 87 // Overview 88 // --------- 89 // 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 95 // the TiledPage. 96 // 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). 100 // 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. 103 // 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. 111 // 112 // Texture allocation 113 // ------------------ 114 // 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. 117 // 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). 122 // 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 128 // 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. 132 // 133 // BaseTile Invalidation 134 // ------------------ 135 // 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 140 // 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. 145 // 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(). 151 // 152 // Painting scheduling 153 // ------------------- 154 // 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. 158 // 159 // BaseTile::paintBitmap() will paint the texture using the BaseLayer's 160 // PictureSet (calling TiledPage::paintBaseLayerContent() which in turns 161 // calls GLWebViewState::paintBaseLayerContent()). 162 // 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). 166 // 167 ///////////////////////////////////////////////////////////////////////////////// 168 169 class GLWebViewState { 170 public: 171 GLWebViewState(); 172 ~GLWebViewState(); 173 174 ZoomManager* zoomManager() { return &m_zoomManager; } 175 const SkIRect& futureViewport() const { return m_futureViewportTileBounds; } 176 void setFutureViewport(const SkIRect& viewport) { m_futureViewportTileBounds = viewport; } 177 178 unsigned int paintBaseLayerContent(SkCanvas* canvas); 179 void setBaseLayer(BaseLayerAndroid* layer, const SkRegion& inval, bool showVisualIndicator, 180 bool isPictureAfterFirstLayout); 181 void paintExtras(); 182 183 GLExtras* glExtras() { return &m_glExtras; } 184 185 TiledPage* sibling(TiledPage* page); 186 TiledPage* frontPage(); 187 TiledPage* backPage(); 188 void swapPages(); 189 190 // dimensions of the current base layer 191 int baseContentWidth(); 192 int baseContentHeight(); 193 194 void setViewport(SkRect& viewport, float scale); 195 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; } 201 202 unsigned int currentPictureCounter() const { return m_currentPictureCounter; } 203 204 void setIsScrolling(bool isScrolling) { m_isScrolling = isScrolling; } 205 bool isScrolling() { return m_isScrolling; } 206 207 void drawBackground(Color& backgroundColor); 208 double setupDrawing(IntRect& viewRect, SkRect& visibleRect, 209 IntRect& webViewRect, int titleBarHeight, 210 IntRect& screenClip, float scale); 211 212 bool setLayersRenderingMode(TexturesResult&); 213 void fullInval(); 214 215 bool drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect, 216 IntRect& webViewRect, int titleBarHeight, 217 IntRect& clip, float scale, 218 bool* treesSwappedPtr, bool* newTreeHasAnimPtr); 219 220 #ifdef MEASURES_PERF 221 void dumpMeasures(); 222 #endif 223 224 void resetFrameworkInval(); 225 void addDirtyArea(const IntRect& rect); 226 void resetLayersDirtyArea(); 227 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; 233 } 234 235 int expandedTileBoundsX() { return m_expandedTileBoundsX; } 236 int expandedTileBoundsY() { return m_expandedTileBoundsY; } 237 void setHighEndGfx(bool highEnd) { m_highEndGfx = highEnd; } 238 239 float scale() { return m_scale; } 240 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. 248 }; 249 250 LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; } 251 void scrollLayer(int layerId, int x, int y); 252 253 void invalRegion(const SkRegion& region); 254 255 private: 256 void inval(const IntRect& rect); 257 258 ZoomManager m_zoomManager; 259 android::Mutex m_tiledPageLock; 260 SkRect m_viewport; 261 SkIRect m_viewportTileBounds; 262 SkIRect m_futureViewportTileBounds; 263 SkIRect m_preZoomBounds; 264 265 unsigned int m_currentPictureCounter; 266 bool m_usePageA; 267 TiledPage* m_tiledPageA; 268 TiledPage* m_tiledPageB; 269 IntRect m_lastInval; 270 IntRect m_frameworkInval; 271 IntRect m_frameworkLayersInval; 272 273 #ifdef MEASURES_PERF 274 unsigned int m_totalTimeCounter; 275 int m_timeCounter; 276 double m_delayTimes[MAX_MEASURES_PERF]; 277 bool m_measurePerfs; 278 #endif 279 GLExtras m_glExtras; 280 281 bool m_isScrolling; 282 bool m_goingDown; 283 bool m_goingLeft; 284 285 int m_expandedTileBoundsX; 286 int m_expandedTileBoundsY; 287 bool m_highEndGfx; 288 289 float m_scale; 290 291 LayersRenderingMode m_layersRenderingMode; 292 TreeManager m_treeManager; 293 }; 294 295 } // namespace WebCore 296 297 #endif // USE(ACCELERATED_COMPOSITING) 298 #endif // GLWebViewState_h 299