OSDN Git Service

4d1dec1bad04869a261102fa6409626094b271e6
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / BaseTileTexture.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 "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 #define LOG_NDEBUG 1
36 #define LOG_TAG "BaseTileTexture.cpp"
37 #include <utils/Log.h>
38
39 namespace WebCore {
40
41 BaseTileTexture::BaseTileTexture(uint32_t w, uint32_t h)
42     : DoubleBufferedTexture(eglGetCurrentContext(), SurfaceTextureMode)
43     , m_usedLevel(-1)
44     , m_owner(0)
45     , m_delayedReleaseOwner(0)
46     , m_delayedRelease(false)
47     , m_busy(false)
48 {
49     m_size.set(w, h);
50
51 #ifdef DEBUG_COUNT
52     ClassTracker::instance()->increment("BaseTileTexture");
53 #endif
54 }
55
56 BaseTileTexture::~BaseTileTexture()
57 {
58     if (m_sharedTextureMode == EglImageMode) {
59         SharedTexture* textures[3] = { m_textureA, m_textureB, 0 };
60         destroyTextures(textures);
61     }
62 #ifdef DEBUG_COUNT
63     ClassTracker::instance()->decrement("BaseTileTexture");
64 #endif
65 }
66
67 void BaseTileTexture::destroyTextures(SharedTexture** textures)
68 {
69     int x = 0;
70     while (textures[x]) {
71         // We need to delete the source texture and EGLImage in the texture
72         // generation thread. In theory we should be able to delete the EGLImage
73         // from either thread, but it currently throws an error if not deleted
74         // in the same EGLContext from which it was created.
75         textures[x]->lock();
76         DeleteTextureOperation* operation = new DeleteTextureOperation(
77             textures[x]->getSourceTextureId(), textures[x]->getEGLImage());
78         textures[x]->unlock();
79         TilesManager::instance()->scheduleOperation(operation);
80         x++;
81     }
82 }
83
84 TextureInfo* BaseTileTexture::producerLock()
85 {
86     m_busyLock.lock();
87     m_busy = true;
88     m_busyLock.unlock();
89     return DoubleBufferedTexture::producerLock();
90 }
91
92 void BaseTileTexture::producerRelease()
93 {
94     DoubleBufferedTexture::producerRelease();
95     setNotBusy();
96 }
97
98 void BaseTileTexture::producerReleaseAndSwap()
99 {
100     DoubleBufferedTexture::producerReleaseAndSwap();
101     setNotBusy();
102 }
103
104 void BaseTileTexture::setNotBusy()
105 {
106     android::Mutex::Autolock lock(m_busyLock);
107     m_busy = false;
108     if (m_delayedRelease) {
109         if (m_owner == m_delayedReleaseOwner)
110             m_owner = 0;
111
112         m_delayedRelease = false;
113         m_delayedReleaseOwner = 0;
114     }
115     m_busyCond.signal();
116 }
117
118 bool BaseTileTexture::busy()
119 {
120     android::Mutex::Autolock lock(m_busyLock);
121     return m_busy;
122 }
123
124 void BaseTileTexture::producerUpdate(TextureInfo* textureInfo, const SkBitmap& bitmap)
125 {
126     // no need to upload a texture since the bitmap is empty
127     if (!bitmap.width() && !bitmap.height()) {
128         producerRelease();
129         return;
130     }
131
132     GLUtils::paintTextureWithBitmap(textureInfo, m_size, bitmap, 0, 0);
133
134     producerReleaseAndSwap();
135 }
136
137 bool BaseTileTexture::acquire(TextureOwner* owner, bool force)
138 {
139     if (m_owner == owner) {
140         if (m_delayedRelease) {
141             m_delayedRelease = false;
142             m_delayedReleaseOwner = 0;
143         }
144         return true;
145     }
146
147     return setOwner(owner, force);
148 }
149
150 bool BaseTileTexture::tryAcquire(TextureOwner* owner)
151 {
152     m_busyLock.lock();
153     if (!m_busy
154         && m_owner
155         && m_owner->state() != owner->state()) {
156         m_busyLock.unlock();
157         return this->acquire(owner);
158     }
159     m_busyLock.unlock();
160     return false;
161 }
162
163 bool BaseTileTexture::setOwner(TextureOwner* owner, bool force)
164 {
165     // if the writable texture is busy (i.e. currently being written to) then we
166     // can't change the owner out from underneath that texture
167     m_busyLock.lock();
168     while (m_busy && force)
169         m_busyCond.wait(m_busyLock);
170     bool busy = m_busy;
171     m_busyLock.unlock();
172
173     if (!busy) {
174         // if we are not busy we can try to remove the texture from the layer;
175         // LayerAndroid::removeTexture() is protected by the same lock as
176         // LayerAndroid::paintBitmapGL(), so either we execute removeTexture()
177         // first and paintBitmapGL() will bail out, or we execute it after,
178         // and paintBitmapGL() will mark the texture as busy before
179         // relinquishing the lock. LayerAndroid::removeTexture() will call
180         // BaseTileTexture::release(), which will then do nothing
181         // if the texture is busy and we then don't return true.
182         bool proceed = true;
183         if (m_owner && m_owner != owner)
184             proceed = m_owner->removeTexture(this);
185
186         if (proceed) {
187             m_owner = owner;
188             return true;
189         }
190     }
191     return false;
192 }
193
194 bool BaseTileTexture::release(TextureOwner* owner)
195 {
196     android::Mutex::Autolock lock(m_busyLock);
197     if (m_owner != owner)
198         return false;
199
200     if (!m_busy) {
201         m_owner = 0;
202     } else {
203         m_delayedRelease = true;
204         m_delayedReleaseOwner = owner;
205     }
206     return true;
207 }
208
209 void BaseTileTexture::setTile(TextureInfo* info, int x, int y,
210                                           float scale, unsigned int pictureCount)
211 {
212     TextureTileInfo* textureInfo = m_texturesInfo.get(getWriteableTexture());
213     if (!textureInfo) {
214         textureInfo = new TextureTileInfo();
215     }
216     textureInfo->m_x = x;
217     textureInfo->m_y = y;
218     textureInfo->m_scale = scale;
219     textureInfo->m_picture = pictureCount;
220     m_texturesInfo.set(getWriteableTexture(), textureInfo);
221 }
222
223 bool BaseTileTexture::readyFor(BaseTile* baseTile)
224 {
225     TextureTileInfo* info = m_texturesInfo.get(getReadableTexture());
226     if (info &&
227         (info->m_x == baseTile->x()) &&
228         (info->m_y == baseTile->y()) &&
229         (info->m_scale == baseTile->scale()) &&
230         (info->m_picture == baseTile->lastPaintedPicture())) {
231         return true;
232     }
233     return false;
234 }
235
236 } // namespace WebCore