OSDN Git Service

Enable double buffering via base tiles
[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 #ifdef DEBUG
37
38 #include <cutils/log.h>
39 #include <wtf/CurrentTime.h>
40 #include <wtf/text/CString.h>
41
42 #undef XLOG
43 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "TiledTexture", __VA_ARGS__)
44
45 #else
46
47 #undef XLOG
48 #define XLOG(...)
49
50 #endif // DEBUG
51
52 namespace WebCore {
53
54 void TiledTexture::prepare(GLWebViewState* state, bool repaint)
55 {
56     if (!m_surface)
57         return;
58
59     if (!m_surface->layer())
60         return;
61
62     // first, how many tiles do we need
63     IntRect visibleArea = m_surface->visibleArea();
64     IntRect area(visibleArea.x() * m_surface->scale(),
65                  visibleArea.y() * m_surface->scale(),
66                  ceilf(visibleArea.width() * m_surface->scale()),
67                  ceilf(visibleArea.height() * m_surface->scale()));
68
69     for (unsigned int i = 0; i < m_tiles.size(); i++) {
70         BaseTile* tile = m_tiles[i];
71         if (!m_dirtyRegion.isEmpty())
72             tile->markAsDirty(1, m_dirtyRegion);
73     }
74     m_dirtyRegion.setEmpty();
75
76     if (area.width() == 0 && area.height() == 0) {
77         m_area.setWidth(0);
78         m_area.setHeight(0);
79         return;
80     }
81
82     int tileWidth = TilesManager::instance()->layerTileWidth();
83     int tileHeight = TilesManager::instance()->layerTileHeight();
84
85     m_area.setX(area.x() / tileWidth);
86     m_area.setY(area.y() / tileHeight);
87     float right = (area.x() + area.width()) / (float) tileWidth;
88     float bottom = (area.y() + area.height()) / (float) tileHeight;
89     m_area.setWidth(ceilf(right) - m_area.x());
90     m_area.setHeight(ceilf(bottom) - m_area.y());
91
92     XLOG("for TiledTexture %x, we have a visible area of %d, %d - %d x %d, corresponding to %d, %d x - %d x %d tiles",
93          this,
94          visibleArea.x(), visibleArea.y(),
95          visibleArea.width(), visibleArea.height(),
96          m_area.x(), m_area.y(),
97          m_area.width(), m_area.height());
98
99     bool goingDown = m_prevTileY < m_area.y();
100     m_prevTileY = m_area.y();
101
102     if (m_surface->scale() != m_prevScale)
103         TilesManager::instance()->removeOperationsForFilter(new ScaleFilter(m_surface->scale()));
104
105     m_prevScale = m_surface->scale();
106
107     for (int i = 0; i < m_area.width(); i++) {
108         if (goingDown) {
109             for (int j = 0; j < m_area.height(); j++) {
110                 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
111             }
112         } else {
113             for (int j = m_area.height() - 1; j >= 0; j--) {
114                 prepareTile(repaint, m_area.x() + i, m_area.y() + j);
115             }
116         }
117     }
118 }
119
120 void TiledTexture::markAsDirty(const SkRegion& dirtyArea)
121 {
122     m_dirtyRegion.op(dirtyArea, SkRegion::kUnion_Op);
123 }
124
125 void TiledTexture::prepareTile(bool repaint, int x, int y)
126 {
127     BaseTile* tile = getTile(x, y);
128     if (!tile) {
129         tile = new BaseTile(true);
130         m_tiles.append(tile);
131     }
132
133     tile->setContents(this, x, y, m_surface->scale());
134
135     // TODO: move below (which is largely the same for layers / tiled page) into
136     // prepare() function
137
138     if (tile->isDirty() || !tile->frontTexture())
139         tile->reserveTexture();
140     LayerAndroid* layer = m_surface->layer();
141     if (tile->backTexture() && tile->isDirty() && !tile->isRepaintPending() && layer) {
142         PaintTileOperation *operation = new PaintTileOperation(tile, m_surface);
143         TilesManager::instance()->scheduleOperation(operation);
144     }
145 }
146
147 BaseTile* TiledTexture::getTile(int x, int y)
148 {
149     for (unsigned int i = 0; i <m_tiles.size(); i++) {
150         BaseTile* tile = m_tiles[i];
151         if (tile->x() == x && tile->y() == y)
152             return tile;
153     }
154     return 0;
155 }
156
157 bool TiledTexture::draw()
158 {
159 #ifdef DEBUG
160     TilesManager::instance()->getTilesTracker()->trackLayer();
161 #endif
162
163     bool askRedraw = false;
164     if (m_area.width() == 0 || m_area.height() == 0)
165         return askRedraw;
166
167 #ifdef DEBUG
168     TilesManager::instance()->getTilesTracker()->trackVisibleLayer();
169 #endif
170
171     float m_invScale = 1 / m_surface->scale();
172     const float tileWidth = TilesManager::layerTileWidth() * m_invScale;
173     const float tileHeight = TilesManager::layerTileHeight() * m_invScale;
174     XLOG("draw tile %x, tiles %d", this, m_tiles.size());
175     for (unsigned int i = 0; i <m_tiles.size(); i++) {
176         BaseTile* tile = m_tiles[i];
177         if (tile->x() >= m_area.x()
178             && tile->x() < m_area.x() + m_area.width()
179             && tile->y() >= m_area.y()
180             && tile->y() < m_area.y() + m_area.height()) {
181             SkRect rect;
182             rect.fLeft = tile->x() * tileWidth;
183             rect.fTop = tile->y() * tileHeight;
184             rect.fRight = rect.fLeft + tileWidth;
185             rect.fBottom = rect.fTop + tileHeight;
186             XLOG(" - [%d], { painter %x vs %x }, tile %x %d,%d at scale %.2f [ready: %d] dirty: %d",
187                  i, this, tile->painter(), tile, tile->x(), tile->y(), tile->scale(), tile->isTileReady(), tile->isDirty());
188             askRedraw |= !tile->isTileReady();
189             tile->swapTexturesIfNeeded();
190             tile->draw(m_surface->opacity(), rect, m_surface->scale());
191 #ifdef DEBUG
192             TilesManager::instance()->getTilesTracker()->track(tile->isTileReady(), tile->backTexture());
193 #endif
194         }
195     }
196     return askRedraw;
197 }
198
199 bool TiledTexture::paint(BaseTile* tile, SkCanvas* canvas, unsigned int* pictureUsed)
200 {
201     if (!m_surface)
202         return false;
203
204     XLOG("painting scheduled tile(%x : %d, %d, %.2f, %x) for %x",
205          tile, tile->x(), tile->y(), tile->scale(), tile->painter(), this);
206     return m_surface->paint(tile, canvas, pictureUsed);
207 }
208
209 void TiledTexture::paintExtra(SkCanvas* canvas)
210 {
211     m_surface->paintExtra(canvas);
212 }
213
214 const TransformationMatrix* TiledTexture::transform()
215 {
216     return m_surface->transform();
217 }
218
219 void TiledTexture::beginPaint()
220 {
221     if (m_surface)
222         m_surface->beginPaint();
223 }
224
225 void TiledTexture::endPaint()
226 {
227     if (m_surface)
228         m_surface->endPaint();
229 }
230
231 void TiledTexture::removeTiles()
232 {
233     for (unsigned int i = 0; i < m_tiles.size(); i++) {
234         delete m_tiles[i];
235     }
236 }
237
238 bool TiledTexture::owns(BaseTileTexture* texture)
239 {
240     for (unsigned int i = 0; i < m_tiles.size(); i++) {
241         BaseTile* tile = m_tiles[i];
242         if (tile->frontTexture() == texture)
243             return true;
244         if (tile->backTexture() == texture)
245             return true;
246     }
247     return false;
248 }
249
250 } // namespace WebCore