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 "PaintedSurface.h"
28
29
30 #include "LayerAndroid.h"
31 #include "TilesManager.h"
32 #include "SkCanvas.h"
33 #include "SkPicture.h"
34
35 #include <cutils/log.h>
36 #include <wtf/CurrentTime.h>
37 #include <wtf/text/CString.h>
38
39 #undef XLOGC
40 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
41
42 #ifdef DEBUG
43
44 #undef XLOG
45 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "PaintedSurface", __VA_ARGS__)
46
47 #else
48
49 #undef XLOG
50 #define XLOG(...)
51
52 #endif // DEBUG
53
54 // Allows layers using less than MAX_UNCLIPPED_AREA tiles to
55 // schedule all of them instead of clipping the area with the visible rect.
56 #define MAX_UNCLIPPED_AREA 16
57
58 namespace WebCore {
59
PaintedSurface(LayerAndroid * layer)60 PaintedSurface::PaintedSurface(LayerAndroid* layer)
61 : m_layer(layer)
62 , m_tiledTexture(0)
63 , m_scale(0)
64 , m_pictureUsed(0)
65 {
66 TilesManager::instance()->addPaintedSurface(this);
67 SkSafeRef(m_layer);
68 #ifdef DEBUG_COUNT
69 ClassTracker::instance()->increment("PaintedSurface");
70 #endif
71 m_tiledTexture = new DualTiledTexture(this);
72 if (layer && layer->picture())
73 m_updateManager.updatePicture(layer->picture());
74 }
75
~PaintedSurface()76 PaintedSurface::~PaintedSurface()
77 {
78 XLOG("dtor of %x m_layer: %x", this, m_layer);
79 android::Mutex::Autolock lock(m_layerLock);
80 SkSafeUnref(m_layer);
81 #ifdef DEBUG_COUNT
82 ClassTracker::instance()->decrement("PaintedSurface");
83 #endif
84 delete m_tiledTexture;
85 }
86
removeLayer()87 void PaintedSurface::removeLayer()
88 {
89 android::Mutex::Autolock lock(m_layerLock);
90 if (m_layer)
91 m_layer->removeTexture(this);
92 SkSafeUnref(m_layer);
93 m_layer = 0;
94 }
95
removeLayer(LayerAndroid * layer)96 void PaintedSurface::removeLayer(LayerAndroid* layer)
97 {
98 android::Mutex::Autolock lock(m_layerLock);
99 if (m_layer != layer)
100 return;
101 SkSafeUnref(m_layer);
102 m_layer = 0;
103 }
104
replaceLayer(LayerAndroid * layer)105 void PaintedSurface::replaceLayer(LayerAndroid* layer)
106 {
107 android::Mutex::Autolock lock(m_layerLock);
108 if (!layer)
109 return;
110
111 if (m_layer && layer->uniqueId() != m_layer->uniqueId())
112 return;
113
114 SkSafeRef(layer);
115 SkSafeUnref(m_layer);
116 m_layer = layer;
117 if (layer && layer->picture())
118 m_updateManager.updatePicture(layer->picture());
119 }
120
prepare(GLWebViewState * state)121 void PaintedSurface::prepare(GLWebViewState* state)
122 {
123 if (!m_layer)
124 return;
125
126 if (!m_layer->needsTexture())
127 return;
128
129 bool startFastSwap = false;
130 if (state->isScrolling()) {
131 // when scrolling, block updates and swap tiles as soon as they're ready
132 startFastSwap = true;
133 } else {
134 // when not, push updates down to TiledTexture in every prepare
135 m_updateManager.swap();
136 m_tiledTexture->update(m_updateManager.getPaintingInval(),
137 m_updateManager.getPaintingPicture());
138 m_updateManager.clearPaintingInval();
139 }
140
141 XLOG("prepare layer %d %x at scale %.2f",
142 m_layer->uniqueId(), m_layer,
143 m_layer->getScale());
144
145 int w = m_layer->getSize().width();
146 int h = m_layer->getSize().height();
147
148 if (w != m_area.width())
149 m_area.setWidth(w);
150
151 if (h != m_area.height())
152 m_area.setHeight(h);
153
154 computeVisibleArea();
155
156 m_scale = state->scale();
157
158 XLOG("%x layer %d %x prepared at size (%d, %d) @ scale %.2f", this, m_layer->uniqueId(),
159 m_layer, w, h, m_scale);
160
161 m_tiledTexture->prepare(state, m_scale, m_pictureUsed != m_layer->pictureUsed(),
162 startFastSwap, m_visibleArea);
163 }
164
draw()165 bool PaintedSurface::draw()
166 {
167 if (!m_layer || !m_layer->needsTexture())
168 return false;
169
170 bool askRedraw = false;
171 if (m_tiledTexture)
172 askRedraw = m_tiledTexture->draw();
173
174 return askRedraw;
175 }
176
markAsDirty(const SkRegion & dirtyArea)177 void PaintedSurface::markAsDirty(const SkRegion& dirtyArea)
178 {
179 m_updateManager.updateInval(dirtyArea);
180 }
181
paintExtra(SkCanvas * canvas)182 void PaintedSurface::paintExtra(SkCanvas* canvas)
183 {
184 m_layerLock.lock();
185 LayerAndroid* layer = m_layer;
186 SkSafeRef(layer);
187 m_layerLock.unlock();
188
189 if (layer)
190 layer->extraDraw(canvas);
191
192 SkSafeUnref(layer);
193 }
194
opacity()195 float PaintedSurface::opacity() {
196 if (m_layer)
197 return m_layer->drawOpacity();
198 return 1.0;
199 }
200
transform()201 const TransformationMatrix* PaintedSurface::transform() {
202 if (!m_layer)
203 return 0;
204
205 return m_layer->drawTransform();
206 }
207
computeVisibleArea()208 void PaintedSurface::computeVisibleArea() {
209 if (!m_layer)
210 return;
211 IntRect layerRect = (*m_layer->drawTransform()).mapRect(m_area);
212 IntRect clippedRect = TilesManager::instance()->shader()->clippedRectWithViewport(layerRect);
213 m_visibleArea = (*m_layer->drawTransform()).inverse().mapRect(clippedRect);
214 if (!m_visibleArea.isEmpty()) {
215 float tileWidth = TilesManager::instance()->layerTileWidth();
216 float tileHeight = TilesManager::instance()->layerTileHeight();
217 int w = ceilf(m_area.width() * m_scale / tileWidth);
218 int h = ceilf(m_area.height() * m_scale / tileHeight);
219 if (w * h < MAX_UNCLIPPED_AREA)
220 m_visibleArea = m_area;
221 }
222 }
223
owns(BaseTileTexture * texture)224 bool PaintedSurface::owns(BaseTileTexture* texture)
225 {
226 if (m_tiledTexture)
227 return m_tiledTexture->owns(texture);
228 return false;
229 }
230
231 } // namespace WebCore
232