2 * Copyright 2011, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "TiledTexture.h"
29 #include "TilesManager.h"
30 #include "TilesTracker.h"
32 #include "PaintedSurface.h"
33 #include "PaintTileOperation.h"
36 #include <cutils/log.h>
37 #include <wtf/CurrentTime.h>
38 #include <wtf/text/CString.h>
41 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
46 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
57 void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSwap)
62 if (!m_surface->layer())
65 // first, how many tiles do we need
66 IntRect visibleArea = m_surface->visibleArea();
67 IntRect area(visibleArea.x() * m_surface->scale(),
68 visibleArea.y() * m_surface->scale(),
69 ceilf(visibleArea.width() * m_surface->scale()),
70 ceilf(visibleArea.height() * m_surface->scale()));
72 if (area.width() == 0 && area.height() == 0) {
78 int tileWidth = TilesManager::instance()->layerTileWidth();
79 int tileHeight = TilesManager::instance()->layerTileHeight();
81 m_area.setX(area.x() / tileWidth);
82 m_area.setY(area.y() / tileHeight);
83 float right = (area.x() + area.width()) / (float) tileWidth;
84 float bottom = (area.y() + area.height()) / (float) tileHeight;
85 m_area.setWidth(ceilf(right) - m_area.x());
86 m_area.setHeight(ceilf(bottom) - m_area.y());
88 XLOG("for TiledTexture %p, we have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
90 visibleArea.x(), visibleArea.y(),
91 visibleArea.width(), visibleArea.height(),
92 m_area.x(), m_area.y(),
93 m_area.width(), m_area.height());
95 bool goingDown = m_prevTileY < m_area.y();
96 m_prevTileY = m_area.y();
98 if (m_surface->scale() != m_prevScale)
99 TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(m_surface->scale()));
101 m_prevScale = m_surface->scale();
103 // unlock if tiles all ready
104 bool tilesAllReady = true;
105 for (unsigned int i = 0; i < m_tiles.size(); i++) {
106 BaseTile* tile = m_tiles[i];
107 if (tile->isTileVisible(m_area) && !tile->isTileReady()) {
108 tilesAllReady = false;
113 // startFastSwap=true will swap all ready tiles each
114 // frame until all visible tiles are up to date
116 m_swapWhateverIsReady = false;
117 else if (startFastSwap)
118 m_swapWhateverIsReady = true;
120 // swap as appropriate
121 for (unsigned int i = 0; i < m_tiles.size(); i++) {
122 BaseTile* tile = m_tiles[i];
123 if (tilesAllReady || m_swapWhateverIsReady)
124 tile->swapTexturesIfNeeded();
128 m_updateManager.swap();
129 m_dirtyRegion.op(m_updateManager.getPaintingInval(), SkRegion::kUnion_Op);
130 XLOG("TT %p swapping, now painting with picture %p"
131 this, m_updateManager.getPaintingPicture());
132 m_updateManager.clearPaintingInval();
135 // apply dirty region to affected tiles
136 if (!m_dirtyRegion.isEmpty()) {
137 for (unsigned int i = 0; i < m_tiles.size(); i++) {
138 // TODO: don't mark all tiles dirty
139 m_tiles[i]->markAsDirty(1, m_dirtyRegion);
142 m_dirtyRegion.setEmpty();
144 for (int i = 0; i < m_area.width(); i++) {
146 for (int j = 0; j < m_area.height(); j++) {
147 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
150 for (int j = m_area.height() - 1; j >= 0; j--) {
151 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
157 void TiledTexture::update(const SkRegion& invalRegion, SkPicture* picture)
159 XLOG("TT %p, update manager %p updated with picture %p, region empty %d",
160 this, &m_updateManager, picture, invalRegion.isEmpty());
161 // attempt to update inval and picture. these may be deferred below instead
162 // of used immediately.
163 m_updateManager.updateInval(invalRegion);
164 m_updateManager.updatePicture(picture);
167 void TiledTexture::prepareTile(bool repaint, int x, int y)
169 BaseTile* tile = getTile(x, y);
171 tile = new BaseTile(true);
172 m_tiles.append(tile);
175 XLOG("preparing tile %p, painter is this %p", tile, this);
176 tile->setContents(this, x, y, m_surface->scale());
178 // TODO: move below (which is largely the same for layers / tiled page) into
179 // prepare() function
181 if (tile->isDirty() || !tile->frontTexture())
182 tile->reserveTexture();
183 LayerAndroid* layer = m_surface->layer();
184 if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && layer) {
185 PaintTileOperation *operation = new PaintTileOperation(tile, m_surface);
186 TilesManager::instance()->scheduleOperation(operation);
190 BaseTile* TiledTexture::getTile(int x, int y)
192 for (unsigned int i = 0; i <m_tiles.size(); i++) {
193 BaseTile* tile = m_tiles[i];
194 if (tile->x() == x && tile->y() == y)
200 bool TiledTexture::draw()
203 TilesManager::instance()->getTilesTracker()->trackLayer();
206 if (m_area.width() == 0 || m_area.height() == 0)
210 TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
213 float m_invScale = 1 / m_surface->scale();
214 const float tileWidth = TilesManager::layerTileWidth() * m_invScale;
215 const float tileHeight = TilesManager::layerTileHeight() * m_invScale;
216 XLOG("draw tile %x, tiles %d", this, m_tiles.size());
218 bool askRedraw = false;
219 for (unsigned int i = 0; i < m_tiles.size(); i++) {
220 BaseTile* tile = m_tiles[i];
222 if (tile->isTileVisible(m_area)) {
223 askRedraw |= !tile->isTileReady();
225 rect.fLeft = tile->x() * tileWidth;
226 rect.fTop = tile->y() * tileHeight;
227 rect.fRight = rect.fLeft + tileWidth;
228 rect.fBottom = rect.fTop + tileHeight;
229 XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f [ready: %d] dirty: %d",
230 i, this, tile->painter(), tile, tile->x(), tile->y(),
231 tile->scale(), tile->isTileReady(), tile->isDirty());
232 tile->draw(m_surface->opacity(), rect, m_surface->scale());
234 TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
239 // need to redraw if some visible tile wasn't ready
243 bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
245 return m_updateManager.paint(tile, canvas, pictureUsed);
248 void TiledTexture::paintExtra(SkCanvas* canvas)
250 m_surface->paintExtra(canvas);
253 const TransformationMatrix* TiledTexture::transform()
255 return m_surface->transform();
258 void TiledTexture::removeTiles()
260 for (unsigned int i = 0; i < m_tiles.size(); i++) {
265 bool TiledTexture::owns(BaseTileTexture* texture)
267 for (unsigned int i = 0; i < m_tiles.size(); i++) {
268 BaseTile* tile = m_tiles[i];
269 if (tile->frontTexture() == texture)
271 if (tile->backTexture() == texture)
277 } // namespace WebCore