• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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