1 /* 2 * Copyright 2011, 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 #define LOG_TAG "SurfaceBacking" 27 #define LOG_NDEBUG 1 28 29 #include "config.h" 30 #include "SurfaceBacking.h" 31 32 #include "AndroidLog.h" 33 #include "Color.h" 34 #include "ClassTracker.h" 35 #include "GLWebViewState.h" 36 #include "LayerAndroid.h" 37 38 #define LOW_RES_PREFETCH_SCALE_MODIFIER 0.3f 39 40 namespace WebCore { 41 42 SurfaceBacking::SurfaceBacking(bool isBaseSurface) 43 : m_frontTileGrid(new TileGrid(isBaseSurface)) 44 , m_backTileGrid(new TileGrid(isBaseSurface)) 45 , m_lowResTileGrid(new TileGrid(isBaseSurface)) 46 , m_scale(-1) 47 , m_futureScale(-1) 48 , m_zooming(false) 49 , m_maxZoomScale(1) 50 51 { 52 #ifdef DEBUG_COUNT 53 ClassTracker::instance()->increment("SurfaceBacking"); 54 #endif 55 } 56 57 SurfaceBacking::~SurfaceBacking() 58 { 59 delete m_frontTileGrid; 60 delete m_backTileGrid; 61 delete m_lowResTileGrid; 62 #ifdef DEBUG_COUNT 63 ClassTracker::instance()->decrement("SurfaceBacking"); 64 #endif 65 } 66 67 void SurfaceBacking::prepareGL(GLWebViewState* state, float maxZoomScale, 68 const IntRect& prepareArea, const IntRect& fullContentArea, 69 TilePainter* painter, bool aggressiveRendering, 70 bool updateWithBlit) 71 { 72 // If the surface backing has ever zoomed beyond 1.0 scale, it's always 73 // allowed to (so repaints aren't necessary when allowZoom toggles). If not, 74 // and allowZoom is false, don't allow scale greater than 1.0 75 m_maxZoomScale = std::max(m_maxZoomScale, maxZoomScale); 76 float scale = state->scale(); 77 bool scaleOverridden = false; 78 if (scale > m_maxZoomScale) { 79 scale = m_maxZoomScale; 80 scaleOverridden = true; 81 } 82 83 if (m_scale == -1) { 84 m_scale = scale; 85 m_futureScale = scale; 86 } 87 88 if (m_futureScale != scale) { 89 m_futureScale = scale; 90 if (scaleOverridden) 91 m_zoomUpdateTime = 0; // start rendering immediately 92 else 93 m_zoomUpdateTime = WTF::currentTime() + SurfaceBacking::s_zoomUpdateDelay; 94 m_zooming = true; 95 96 // release back TileGrid's TileTextures, so they can be reused immediately 97 m_backTileGrid->discardTextures(); 98 } 99 100 int prepareRegionFlags = TileGrid::StandardRegion; 101 if (aggressiveRendering) 102 prepareRegionFlags |= TileGrid::ExpandedRegion; 103 104 ALOGV("Prepare SurfBack %p, scale %.2f, m_scale %.2f, futScale: %.2f, zooming: %d, f %p, b %p", 105 this, scale, m_scale, m_futureScale, m_zooming, 106 m_frontTileGrid, m_backTileGrid); 107 108 if (m_zooming && (m_zoomUpdateTime < WTF::currentTime())) { 109 // prepare the visible portions of the back tile grid at the futureScale 110 m_backTileGrid->prepareGL(state, m_futureScale, 111 prepareArea, fullContentArea, painter, 112 TileGrid::StandardRegion, false); 113 114 if (m_backTileGrid->isReady()) { 115 // zooming completed, swap the TileGrids and new front tiles 116 swapTileGrids(); 117 118 m_frontTileGrid->swapTiles(); 119 m_backTileGrid->discardTextures(); 120 m_lowResTileGrid->discardTextures(); 121 122 m_scale = m_futureScale; 123 m_zooming = false; 124 125 // clear the StandardRegion flag, to prevent preparing it twice - 126 // the new frontTileGrid has already had its StandardRegion prepared 127 prepareRegionFlags &= ~TileGrid::StandardRegion; 128 } 129 } 130 131 if (!m_zooming) { 132 if (prepareRegionFlags) { 133 // if the front grid hasn't already prepared, or needs to prepare 134 // expanded bounds do so now 135 m_frontTileGrid->prepareGL(state, m_scale, 136 prepareArea, fullContentArea, painter, 137 prepareRegionFlags, false, updateWithBlit); 138 } 139 if (aggressiveRendering) { 140 // prepare low res content 141 float lowResPrefetchScale = m_scale * LOW_RES_PREFETCH_SCALE_MODIFIER; 142 m_lowResTileGrid->prepareGL(state, lowResPrefetchScale, 143 prepareArea, fullContentArea, painter, 144 TileGrid::StandardRegion | TileGrid::ExpandedRegion, true); 145 m_lowResTileGrid->swapTiles(); 146 } 147 } 148 } 149 150 void SurfaceBacking::drawGL(const IntRect& visibleContentArea, float opacity, 151 const TransformationMatrix* transform, 152 bool aggressiveRendering, const Color* background) 153 { 154 // draw low res prefetch page if zooming or front texture missing content 155 if (aggressiveRendering && isMissingContent()) 156 m_lowResTileGrid->drawGL(visibleContentArea, opacity, transform); 157 158 m_frontTileGrid->drawGL(visibleContentArea, opacity, transform, background); 159 } 160 161 void SurfaceBacking::markAsDirty(const SkRegion& dirtyArea) 162 { 163 m_backTileGrid->markAsDirty(dirtyArea); 164 m_frontTileGrid->markAsDirty(dirtyArea); 165 m_lowResTileGrid->markAsDirty(dirtyArea); 166 } 167 168 bool SurfaceBacking::swapTiles() 169 { 170 bool swap = m_backTileGrid->swapTiles(); 171 swap |= m_frontTileGrid->swapTiles(); 172 swap |= m_lowResTileGrid->swapTiles(); 173 return swap; 174 } 175 176 void SurfaceBacking::computeTexturesAmount(TexturesResult* result, 177 const IntRect& visibleContentArea, 178 const IntRect& fullContentArea, 179 LayerAndroid* layer) 180 { 181 182 // get two numbers here: 183 // - textures needed for a clipped area 184 // - textures needed for an un-clipped area 185 TileGrid* tileGrid = m_zooming ? m_backTileGrid : m_frontTileGrid; 186 int nbTexturesUnclipped = tileGrid->nbTextures(fullContentArea, m_futureScale); 187 int nbTexturesClipped = tileGrid->nbTextures(visibleContentArea, m_futureScale); 188 189 if (layer) { 190 // TODO: should handle multi-layer case better 191 192 // Set kFixedLayers level 193 if (layer->isPositionFixed()) 194 result->fixed += nbTexturesClipped; 195 196 // Set kScrollableAndFixedLayers level 197 if (layer->contentIsScrollable() 198 || layer->isPositionFixed()) 199 result->scrollable += nbTexturesClipped; 200 } 201 202 // Set kClippedTextures level 203 result->clipped += nbTexturesClipped; 204 205 // Set kAllTextures level 206 if (layer && layer->contentIsScrollable()) 207 result->full += nbTexturesClipped; 208 else 209 result->full += nbTexturesUnclipped; 210 } 211 212 void SurfaceBacking::swapTileGrids() 213 { 214 TileGrid* temp = m_frontTileGrid; 215 m_frontTileGrid = m_backTileGrid; 216 m_backTileGrid = temp; 217 } 218 219 } // namespace WebCore 220