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