OSDN Git Service

Merge "Fallback handle if vertical glyphs are missing."
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / TiledTexture.cpp
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 #include "config.h"
27 #include "TiledTexture.h"
28
29 #include "TilesManager.h"
30 #include "TilesTracker.h"
31
32 #include "PaintedSurface.h"
33 #include "PaintTileOperation.h"
34 #include "SkCanvas.h"
35
36 #include <cutils/log.h>
37 #include <wtf/CurrentTime.h>
38 #include <wtf/text/CString.h>
39
40 #undef XLOGC
41 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
42
43 #ifdef DEBUG
44
45 #undef XLOG
46 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
47
48 #else
49
50 #undef XLOG
51 #define XLOG(...)
52
53 #endif // DEBUG
54
55 namespace WebCore {
56
57 void TiledTexture::prepare(GLWebViewState* state, bool repaint, bool startFastSwap)
58 {
59     if (!m_surface)
60         return;
61
62     if (!m_surface->layer())
63         return;
64
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()));
71
72     if (area.width() == 0 && area.height() == 0) {
73         m_area.setWidth(0);
74         m_area.setHeight(0);
75         return;
76     }
77
78     int tileWidth = TilesManager::instance()->layerTileWidth();
79     int tileHeight = TilesManager::instance()->layerTileHeight();
80
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());
87
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",
89          this,
90          visibleArea.x(), visibleArea.y(),
91          visibleArea.width(), visibleArea.height(),
92          m_area.x(), m_area.y(),
93          m_area.width(), m_area.height());
94
95     bool goingDown = m_prevTileY < m_area.y();
96     m_prevTileY = m_area.y();
97
98     if (m_surface->scale() != m_prevScale)
99         TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(m_surface->scale()));
100
101     m_prevScale = m_surface->scale();
102
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;
109             break;
110         }
111     }
112
113     // startFastSwap=true will swap all ready tiles each
114     // frame until all visible tiles are up to date
115     if (tilesAllReady)
116         m_swapWhateverIsReady = false;
117     else if (startFastSwap)
118         m_swapWhateverIsReady = true;
119
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();
125     }
126
127     if (tilesAllReady) {
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();
133     }
134
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);
140         }
141     }
142     m_dirtyRegion.setEmpty();
143
144     for (int i = 0; i < m_area.width(); i++) {
145         if (goingDown) {
146             for (int j = 0; j < m_area.height(); j++) {
147                 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
148             }
149         } else {
150             for (int j = m_area.height() - 1; j >= 0; j--) {
151                 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
152             }
153         }
154     }
155 }
156
157 void TiledTexture::update(const SkRegion& invalRegion, SkPicture* picture)
158 {
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);
165 }
166
167 void TiledTexture::prepareTile(bool repaint, int x, int y)
168 {
169     BaseTile* tile = getTile(x, y);
170     if (!tile) {
171         tile = new BaseTile(true);
172         m_tiles.append(tile);
173     }
174
175     XLOG("preparing tile %p, painter is this %p", tile, this);
176     tile->setContents(this, x, y, m_surface->scale());
177
178     // TODO: move below (which is largely the same for layers / tiled page) into
179     // prepare() function
180
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);
187     }
188 }
189
190 BaseTile* TiledTexture::getTile(int x, int y)
191 {
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)
195             return tile;
196     }
197     return 0;
198 }
199
200 bool TiledTexture::draw()
201 {
202 #ifdef DEBUG
203     TilesManager::instance()->getTilesTracker()->trackLayer();
204 #endif
205
206     if (m_area.width() == 0 || m_area.height() == 0)
207         return false;
208
209 #ifdef DEBUG
210     TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
211 #endif
212
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());
217
218     bool askRedraw = false;
219     for (unsigned int i = 0; i < m_tiles.size(); i++) {
220         BaseTile* tile = m_tiles[i];
221
222         if (tile->isTileVisible(m_area)) {
223             askRedraw |= !tile->isTileReady();
224             SkRect rect;
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());
233 #ifdef DEBUG
234             TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
235 #endif
236         }
237     }
238
239     // need to redraw if some visible tile wasn't ready
240     return askRedraw;
241 }
242
243 bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
244 {
245     return m_updateManager.paint(tile, canvas, pictureUsed);
246 }
247
248 void TiledTexture::paintExtra(SkCanvas* canvas)
249 {
250     m_surface->paintExtra(canvas);
251 }
252
253 const TransformationMatrix* TiledTexture::transform()
254 {
255     return m_surface->transform();
256 }
257
258 void TiledTexture::removeTiles()
259 {
260     for (unsigned int i = 0; i < m_tiles.size(); i++) {
261         delete m_tiles[i];
262     }
263 }
264
265 bool TiledTexture::owns(BaseTileTexture* texture)
266 {
267     for (unsigned int i = 0; i < m_tiles.size(); i++) {
268         BaseTile* tile = m_tiles[i];
269         if (tile->frontTexture() == texture)
270             return true;
271         if (tile->backTexture() == texture)
272             return true;
273     }
274     return false;
275 }
276
277 } // namespace WebCore