Home | History | Annotate | Download | only in rendering
      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