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