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 "BaseTileTexture.h"
28
29 #include "BaseTile.h"
30 #include "ClassTracker.h"
31 #include "DeleteTextureOperation.h"
32 #include "GLUtils.h"
33 #include "TilesManager.h"
34
35 #include <cutils/log.h>
36 #include <wtf/text/CString.h>
37
38 #undef XLOGC
39 #define XLOGC(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
40
41 #ifdef DEBUG
42
43 #undef XLOG
44 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "BaseTileTexture", __VA_ARGS__)
45
46 #else
47
48 #undef XLOG
49 #define XLOG(...)
50
51 #endif // DEBUG
52
53 namespace WebCore {
54
BaseTileTexture(uint32_t w,uint32_t h)55 BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h)
56 : DoubleBufferedTexture(eglGetCurrentContext(),
57 TilesManager::instance()->getSharedTextureMode())
58 , m_owner(0)
59 , m_busy(false)
60 {
61 m_size.set(w, h);
62 m_ownTextureId = 0;
63
64 // Make sure they are created on the UI thread.
65 TilesManager::instance()->transferQueue()->initSharedSurfaceTextures(w, h);
66
67 #ifdef DEBUG_COUNT
68 ClassTracker::instance()->increment("BaseTileTexture");
69 #endif
70 }
71
~BaseTileTexture()72 BaseTileTexture::~BaseTileTexture()
73 {
74 if (m_sharedTextureMode == EglImageMode) {
75 SharedTexture* textures[3] = { m_textureA, m_textureB, 0 };
76 destroyTextures(textures);
77 }
78 #ifdef DEBUG_COUNT
79 ClassTracker::instance()->decrement("BaseTileTexture");
80 #endif
81 }
82
requireGLTexture()83 void BaseTileTexture::requireGLTexture()
84 {
85 if (!m_ownTextureId)
86 m_ownTextureId = GLUtils::createBaseTileGLTexture(m_size.width(), m_size.height());
87 }
88
discardGLTexture()89 void BaseTileTexture::discardGLTexture()
90 {
91 if (m_ownTextureId)
92 GLUtils::deleteTexture(&m_ownTextureId);
93
94 if (m_owner) {
95 // clear both Tile->Texture and Texture->Tile links
96 m_owner->removeTexture(this);
97 release(m_owner);
98 }
99 }
100
destroyTextures(SharedTexture ** textures)101 void BaseTileTexture::destroyTextures(SharedTexture** textures)
102 {
103 int x = 0;
104 while (textures[x]) {
105 // We need to delete the source texture and EGLImage in the texture
106 // generation thread. In theory we should be able to delete the EGLImage
107 // from either thread, but it currently throws an error if not deleted
108 // in the same EGLContext from which it was created.
109 textures[x]->lock();
110 DeleteTextureOperation* operation = new DeleteTextureOperation(
111 textures[x]->getSourceTextureId(), textures[x]->getEGLImage());
112 textures[x]->unlock();
113 TilesManager::instance()->scheduleOperation(operation);
114 x++;
115 }
116 }
117
producerLock()118 TextureInfo* BaseTileTexture::producerLock()
119 {
120 m_busyLock.lock();
121 m_busy = true;
122 m_busyLock.unlock();
123 return DoubleBufferedTexture::producerLock();
124 }
125
producerRelease()126 void BaseTileTexture::producerRelease()
127 {
128 DoubleBufferedTexture::producerRelease();
129 setNotBusy();
130 }
131
producerReleaseAndSwap()132 void BaseTileTexture::producerReleaseAndSwap()
133 {
134 DoubleBufferedTexture::producerReleaseAndSwap();
135 setNotBusy();
136 }
137
setNotBusy()138 void BaseTileTexture::setNotBusy()
139 {
140 android::Mutex::Autolock lock(m_busyLock);
141 m_busy = false;
142 m_busyCond.signal();
143 }
144
busy()145 bool BaseTileTexture::busy()
146 {
147 android::Mutex::Autolock lock(m_busyLock);
148 return m_busy;
149 }
150
producerUpdate(TextureInfo * textureInfo,const SkBitmap & bitmap)151 void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap)
152 {
153 // no need to upload a texture since the bitmap is empty
154 if (!bitmap.width() && !bitmap.height()) {
155 producerRelease();
156 return;
157 }
158
159 // After the tiled layer checked in, this is not called anyway.
160 // TODO: cleanup the old code path for layer painting
161 // GLUtils::paintTextureWithBitmap(info, m_size, bitmap, 0, 0);
162
163 producerReleaseAndSwap();
164 }
165
acquire(TextureOwner * owner,bool force)166 bool BaseTileTexture::acquire(TextureOwner* owner, bool force)
167 {
168 if (m_owner == owner)
169 return true;
170
171 return setOwner(owner, force);
172 }
173
setOwner(TextureOwner * owner,bool force)174 bool BaseTileTexture::setOwner(TextureOwner* owner, bool force)
175 {
176 // if the writable texture is busy (i.e. currently being written to) then we
177 // can't change the owner out from underneath that texture
178 m_busyLock.lock();
179 while (m_busy && force)
180 m_busyCond.wait(m_busyLock);
181 bool busy = m_busy;
182 m_busyLock.unlock();
183
184 if (!busy) {
185 // if we are not busy we can try to remove the texture from the layer;
186 // LayerAndroid::removeTexture() is protected by the same lock as
187 // LayerAndroid::paintBitmapGL(), so either we execute removeTexture()
188 // first and paintBitmapGL() will bail out, or we execute it after,
189 // and paintBitmapGL() will mark the texture as busy before
190 // relinquishing the lock. LayerAndroid::removeTexture() will call
191 // BaseTileTexture::release(), which will then do nothing
192 // if the texture is busy and we then don't return true.
193 bool proceed = true;
194 if (m_owner && m_owner != owner)
195 proceed = m_owner->removeTexture(this);
196
197 if (proceed) {
198 m_owner = owner;
199 return true;
200 }
201 }
202 return false;
203 }
204
release(TextureOwner * owner)205 bool BaseTileTexture::release(TextureOwner* owner)
206 {
207 android::Mutex::Autolock lock(m_busyLock);
208 XLOG("texture %p releasing tile %p, m_owner %p, m_busy %d", this, owner, m_owner, m_busy);
209 if (m_owner != owner)
210 return false;
211
212 m_owner = 0;
213 return true;
214 }
215
setTile(TextureInfo * info,int x,int y,float scale,TilePainter * painter,unsigned int pictureCount)216 void BaseTileTexture::setTile(TextureInfo* info, int x, int y,
217 float scale, TilePainter* painter,
218 unsigned int pictureCount)
219 {
220 TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture());
221 if (!textureInfo) {
222 textureInfo = new TextureTileInfo();
223 }
224 textureInfo->m_x = x;
225 textureInfo->m_y = y;
226 textureInfo->m_scale = scale;
227 textureInfo->m_painter = painter;
228 textureInfo->m_picture = pictureCount;
229 m_texturesInfo.set(getWriteableTexture(), textureInfo);
230 }
231
scale()232 float BaseTileTexture::scale()
233 {
234 TextureTileInfo* textureInfo = &m_ownTextureTileInfo;
235 return textureInfo->m_scale;
236 }
237
238 // This function + TilesManager::addItemInTransferQueue() is replacing the
239 // setTile().
setOwnTextureTileInfoFromQueue(const TextureTileInfo * info)240 void BaseTileTexture::setOwnTextureTileInfoFromQueue(const TextureTileInfo* info)
241 {
242 m_ownTextureTileInfo.m_x = info->m_x;
243 m_ownTextureTileInfo.m_y = info->m_y;
244 m_ownTextureTileInfo.m_scale = info->m_scale;
245 m_ownTextureTileInfo.m_painter = info->m_painter;
246 m_ownTextureTileInfo.m_picture = info->m_picture;
247 m_ownTextureTileInfo.m_inverted = TilesManager::instance()->invertedScreen();
248 if (m_owner) {
249 BaseTile* owner = static_cast<BaseTile*>(m_owner);
250 owner->backTextureTransfer();
251 }
252
253 }
254
readyFor(BaseTile * baseTile)255 bool BaseTileTexture::readyFor(BaseTile* baseTile)
256 {
257 const TextureTileInfo* info = &m_ownTextureTileInfo;
258 if (info &&
259 (info->m_x == baseTile->x()) &&
260 (info->m_y == baseTile->y()) &&
261 (info->m_scale == baseTile->scale()) &&
262 (info->m_painter == baseTile->painter()) &&
263 (info->m_inverted == TilesManager::instance()->invertedScreen()))
264 return true;
265
266 XLOG("texture %p readyFor return false for tile x, y (%d %d) texId %d ,"
267 " BaseTileTexture %p, BaseTile is %p, SCALE %f, painter %p, inv %d",
268 this, baseTile->x(), baseTile->y(), m_ownTextureId, this, baseTile,
269 baseTile->scale(), baseTile->painter(), TilesManager::instance()->invertedScreen());
270 return false;
271 }
272
273 } // namespace WebCore
274