OSDN Git Service

Merge "Ensure non-ready tiles are painted with the page background color."
[android-x86/external-webkit.git] / WebCore / platform / graphics / android / BaseTile.cpp
1 /*
2  * Copyright 2010, 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 "BaseTile.h"
28
29 #if USE(ACCELERATED_COMPOSITING)
30
31 #include "GLUtils.h"
32 #include "SkBitmap.h"
33 #include "SkBitmapRef.h"
34 #include "SkCanvas.h"
35 #include "TilesManager.h"
36
37 #include <EGL/egl.h>
38 #include <EGL/eglext.h>
39 #include <GLES2/gl2.h>
40 #include <GLES2/gl2ext.h>
41 #include <cutils/atomic.h>
42
43 #ifdef DEBUG
44
45 #include <cutils/log.h>
46 #include <wtf/CurrentTime.h>
47 #include <wtf/text/CString.h>
48
49 #undef XLOG
50 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTile", __VA_ARGS__)
51
52 #else
53
54 #undef XLOG
55 #define XLOG(...)
56
57 #endif // DEBUG
58
59 namespace WebCore {
60
61 BaseTile::BaseTile()
62     : m_page(0)
63     , m_x(-1)
64     , m_y(-1)
65     , m_texture(0)
66     , m_scale(1)
67     , m_dirty(true)
68     , m_usable(true)
69     , m_lastDirtyPicture(0)
70     , m_lastPaintedPicture(0)
71 {
72 #ifdef DEBUG_COUNT
73     ClassTracker::instance()->increment("BaseTile");
74 #endif
75 }
76
77 BaseTile::~BaseTile()
78 {
79     setUsedLevel(-1);
80     if (m_texture)
81         m_texture->release(this);
82
83 #ifdef DEBUG_COUNT
84     ClassTracker::instance()->decrement("BaseTile");
85 #endif
86 }
87
88 // All the following functions must be called from the main GL thread.
89
90 void BaseTile::setContents(TiledPage* page, int x, int y)
91 {
92     android::AutoMutex lock(m_atomicSync);
93     m_page = page;
94     m_x = x;
95     m_y = y;
96 }
97
98 void BaseTile::reserveTexture()
99 {
100     BackedDoubleBufferedTexture* texture = TilesManager::instance()->getAvailableTexture(this);
101
102     android::AutoMutex lock(m_atomicSync);
103     if (m_texture != texture) {
104         m_lastPaintedPicture = 0;
105         m_dirty = true;
106     }
107     m_texture = texture;
108 }
109
110 bool BaseTile::removeTexture(BackedDoubleBufferedTexture* texture)
111 {
112     XLOG("%x removeTexture res: %x... page %x", this, m_texture, m_page);
113     // We update atomically, so paintBitmap() can see the correct value
114     android::AutoMutex lock(m_atomicSync);
115     if (m_texture == texture)
116         m_texture = 0;
117     return true;
118 }
119
120 void BaseTile::setScale(float scale)
121 {
122     android::AutoMutex lock(m_atomicSync);
123     if (m_scale != scale)
124         m_dirty = true;
125     m_scale = scale;
126 }
127
128 void BaseTile::markAsDirty(int unsigned pictureCount)
129 {
130     android::AutoMutex lock(m_atomicSync);
131     m_lastDirtyPicture = pictureCount;
132     if (m_lastPaintedPicture < m_lastDirtyPicture)
133         m_dirty = true;
134 }
135
136 void BaseTile::setUsable(bool usable)
137 {
138     android::AutoMutex lock(m_atomicSync);
139     m_usable = usable;
140 }
141
142
143 bool BaseTile::isDirty()
144 {
145     android::AutoMutex lock(m_atomicSync);
146     return m_dirty;
147 }
148
149 void BaseTile::setUsedLevel(int usedLevel)
150 {
151     if (m_texture)
152         m_texture->setUsedLevel(usedLevel);
153 }
154
155 void BaseTile::draw(float transparency, SkRect& rect)
156 {
157     // No need to mutex protect reads of m_texture as it is only written to by
158     // the consumer thread.
159     if (!m_texture) {
160         XLOG("%x on page %x (%d, %d) trying to draw, but no m_texture!", this, m_page, x(), y());
161         return;
162     }
163
164     // Early return if set to un-usable in purpose!
165     m_atomicSync.lock();
166     bool usable = m_usable;
167     bool isTexturePainted = m_lastPaintedPicture;
168     m_atomicSync.unlock();
169     if (!usable) {
170         XLOG("early return at BaseTile::draw b/c tile set to unusable !");
171         return;
172     }
173     if (!isTexturePainted) {
174         XLOG("early return at BaseTile::draw b/c tile is not painted !");
175         return;
176     }
177
178     if (m_texture->x() != m_x || m_texture->y() != m_y)
179         return;
180
181     TextureInfo* textureInfo = m_texture->consumerLock();
182     if (!textureInfo) {
183         XLOG("%x (%d, %d) trying to draw, but no textureInfo!", this, x(), y());
184         m_texture->consumerRelease();
185         return;
186     }
187
188     TilesManager::instance()->shader()->drawQuad(rect, textureInfo->m_textureId,
189                                                  transparency);
190
191     m_texture->consumerRelease();
192 }
193
194 bool BaseTile::isTileReady()
195 {
196     if (!m_texture)
197         return false;
198     if (m_texture->owner() != this)
199         return false;
200
201     android::AutoMutex lock(m_atomicSync);
202     return !m_dirty;
203 }
204
205 void BaseTile::drawTileInfo(SkCanvas* canvas,
206                             BackedDoubleBufferedTexture* texture,
207                             int x, int y, float scale)
208 {
209     SkPaint paint;
210     char str[256];
211     snprintf(str, 256, "(%d,%d) %.2f, tile %x, texture: %x",
212              x, y, scale, this, texture);
213     paint.setARGB(255, 0, 0, 0);
214     canvas->drawText(str, strlen(str), 50, 100, paint);
215     paint.setARGB(255, 255, 0, 0);
216     canvas->drawText(str, strlen(str), 51, 101, paint);
217 }
218
219 // This is called from the texture generation thread
220 void BaseTile::paintBitmap()
221 {
222
223     // We acquire the values below atomically. This ensures that we are reading
224     // values correctly across cores. Further, once we have these values they
225     // can be updated by other threads without consequence.
226     m_atomicSync.lock();
227     bool dirty = m_dirty;
228     BackedDoubleBufferedTexture* texture = m_texture;
229     float scale = m_scale;
230     m_atomicSync.unlock();
231
232     if (!dirty || !texture)
233         return;
234
235     const int x = m_x;
236     const int y = m_y;
237     TiledPage* tiledPage = m_page;
238
239     texture->producerAcquireContext();
240     TextureInfo* textureInfo = texture->producerLock();
241
242     // at this point we can safely check the ownership (if the texture got
243     // transferred to another BaseTile under us)
244     if (texture->owner() != this || texture->usedLevel() > 1) {
245         texture->producerRelease();
246         return;
247     }
248
249     SkSize size = texture->getSize();
250     float tileWidth = size.width();
251     float tileHeight = size.height();
252
253     const float invScale = 1 / scale;
254     float w = tileWidth * invScale;
255     float h = tileHeight * invScale;
256
257     SkCanvas* canvas = texture->canvas();
258
259     canvas->save();
260     canvas->drawColor(tiledPage->glWebViewState()->getBackgroundColor());
261     canvas->scale(scale, scale);
262     canvas->translate(-x * w, -y * h);
263
264     unsigned int pictureCount = tiledPage->paintBaseLayerContent(canvas);
265
266     canvas->restore();
267
268     if (TilesManager::instance()->getShowVisualIndicator()) {
269         SkPaint paint;
270         paint.setARGB(128, 255, 0, 0);
271         paint.setStrokeWidth(3);
272         canvas->drawLine(0, 0, tileWidth, tileHeight, paint);
273         paint.setARGB(128, 0, 255, 0);
274         canvas->drawLine(0, tileHeight, tileWidth, 0, paint);
275         paint.setARGB(128, 0, 0, 255);
276         canvas->drawLine(0, 0, tileWidth, 0, paint);
277         canvas->drawLine(tileWidth, 0, tileWidth, tileHeight, paint);
278         drawTileInfo(canvas, texture, x, y, scale);
279     }
280
281     texture->setTile(x, y);
282     texture->producerUpdate(textureInfo);
283
284     m_atomicSync.lock();
285     m_lastPaintedPicture = pictureCount;
286     if (m_lastPaintedPicture >= m_lastDirtyPicture) {
287         m_dirty = false;
288         m_usable = true;
289     }
290     m_atomicSync.unlock();
291 }
292
293 } // namespace WebCore
294
295 #endif // USE(ACCELERATED_COMPOSITING)