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 52 namespace WebCore { 53 54 class BaseLayerAndroid; 55 class LayerAndroid; 56 class ScrollableLayerAndroid; 57 class 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 164 class GLWebViewState { 165 public: 166 GLWebViewState(); 167 ~GLWebViewState(); 168 169 bool setBaseLayer(BaseLayerAndroid* layer, bool showVisualIndicator, 170 bool isPictureAfterFirstLayout); 171 void paintExtras(); 172 glExtras()173 GLExtras* glExtras() { return &m_glExtras; } 174 setIsScrolling(bool isScrolling)175 void setIsScrolling(bool isScrolling) { m_isScrolling = 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(); inUnclippedDraw()193 bool inUnclippedDraw() { return m_inUnclippedDraw; } 194 goingDown()195 bool goingDown() { return m_goingDown; } goingLeft()196 bool goingLeft() { return m_goingLeft; } 197 scale()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 layersRenderingMode()211 LayersRenderingMode layersRenderingMode() { return m_layersRenderingMode; } isSingleSurfaceRenderingMode()212 bool isSingleSurfaceRenderingMode() { return m_layersRenderingMode == kSingleSurfaceRendering; } 213 void scrollLayer(int layerId, int x, int y); 214 215 private: 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