2 * Copyright (C) 2012 Samsung Electronics. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. 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.
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY 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.
28 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE)
29 #include "PlatformSurfacePoolTizen.h"
30 #include <WebCore/Logging.h>
31 #include <wtf/HashMap.h>
32 #include "WebProcess.h"
33 #include "WebProcessProxyMessages.h"
35 using namespace WebCore;
38 static const int MB = 1024 * 1024;
40 static inline bool reachLowPoolUtilization(int usedSize, int totalSize)
42 // lowPoolUtilization threshold is 70%.
43 return (usedSize < static_cast<int>(static_cast<float>(totalSize) * 0.7));
46 static inline bool reachHighPoolUtilization(int usedSize, int totalSize)
48 // highPoolUtilization threshold is 90%.
49 return (usedSize > static_cast<int>(static_cast<float>(totalSize) * 0.9));
52 PlatformSurfacePoolTizen::PlatformSurfaceInfo::PlatformSurfaceInfo(const IntSize& size)
54 , m_willBeRemoved(false)
58 m_SharedPlatformSurfaceTizen = WebCore::SharedPlatformSurfaceTizen::create(size, true);
61 PlatformSurfacePoolTizen::PlatformSurfacePoolTizen()
63 , m_maxSizeInByte(128 * MB) // 128 MB
65 , m_usedSizeInCount(0)
66 , m_removePlaformSurfaceTimer(this, &PlatformSurfacePoolTizen::removePlaformSurfaceTimerFired)
68 // FIXME : Create this workqueue and a pixmap temporarily to avoid a crash issue.
69 // The crash occur in cairo gl used by 2dCanvas. It will be removed if the issue is fixed.
70 RefPtr<PlatformSurfaceInfo> newPlatformSurfaceInfo;
71 newPlatformSurfaceInfo = createPlatformSurface(IntSize(384,384));
74 PlatformSurfacePoolTizen::~PlatformSurfacePoolTizen()
76 m_platformSurfacesToFree.clear();
78 PlatformSurfaceMap::iterator end = m_platformSurfaces.end();
79 for (PlatformSurfaceMap::iterator iter = m_platformSurfaces.begin(); iter != end; ++iter) {
80 iter->second->m_SharedPlatformSurfaceTizen.release();
81 iter->second.release();
83 m_platformSurfaces.clear();
86 SharedPlatformSurfaceTizen* PlatformSurfacePoolTizen::acquirePlatformSurface(const IntSize& size, int tileID)
88 freePlatformSurfacesIfNeeded();
89 removePlatformSurfacesIfNeeded();
90 PlatformSurfaceMap::iterator end = m_platformSurfaces.end();
91 for (PlatformSurfaceMap::iterator iter = m_platformSurfaces.begin(); iter != end; ++iter) {
92 RefPtr<PlatformSurfaceInfo> platformSurfaceInfo = iter->second;
93 if (platformSurfaceInfo->m_used || platformSurfaceInfo->m_willBeRemoved)
96 if (platformSurfaceInfo->size() != size)
97 platformSurfaceInfo->m_age++;
99 platformSurfaceInfo->m_used = true;
100 platformSurfaceInfo->m_age = 0;
101 platformSurfaceInfo->m_tileID = tileID;
104 m_usedSizeInByte += platformSurfaceInfo->sizeInByte();
107 LOG(TiledAC, "XPlatformSurface pool size : %u MB (%u tiles) used : %u MB (%u tiles) at [%s]",
108 m_sizeInByte/MB, m_platformSurfaces.size(), m_usedSizeInByte/MB, m_usedSizeInCount, "PlatformSurfacePoolTizen::acquirePlatformSurface");
109 return platformSurfaceInfo->m_SharedPlatformSurfaceTizen.get();
113 if (canCreatePlatformSurface()) {
114 RefPtr<PlatformSurfaceInfo> newPlatformSurfaceInfo = createPlatformSurface(size);
115 if (!newPlatformSurfaceInfo) {
116 LOG(TiledAC, "can't create new platformSurface(%dx%d) at [%s]", size.width(), size.height(), "PlatformSurfacePoolTizen::acquirePlatformSurface");
119 newPlatformSurfaceInfo->m_used = true;
120 newPlatformSurfaceInfo->m_tileID = tileID;
123 m_usedSizeInByte += newPlatformSurfaceInfo->sizeInByte();
125 LOG(TiledAC, "acquire platformSurface(%dx%d) XPlatformSurface pool size : %u MB (%u tiles) used : %u MB (%u tiles) at [%s]",
126 size.width(), size.height(), m_sizeInByte/MB, m_platformSurfaces.size(), m_usedSizeInByte/MB, m_usedSizeInCount, "PlatformSurfacePoolTizen::acquirePlatformSurface");
128 return newPlatformSurfaceInfo->m_SharedPlatformSurfaceTizen.get();
131 LOG(TiledAC, "No more platformSurface allowed: can't acquire platformSurface(%dx%d) at [%s]", size.width(), size.height(), "PlatformSurfacePoolTizen::acquirePlatformSurface");
135 SharedPlatformSurfaceTizen* PlatformSurfacePoolTizen::acquirePlatformSurfaceByID(int platformSurfaceId)
137 PlatformSurfaceMap::iterator foundSurface = m_platformSurfaces.find(platformSurfaceId);
138 if (foundSurface == m_platformSurfaces.end())
140 return foundSurface->second->m_SharedPlatformSurfaceTizen.get();
143 void PlatformSurfacePoolTizen::freePlatformSurfaceByTileID(int tileID)
145 int platformSurfaceId = 0;
146 PlatformSurfaceMap::iterator end = m_platformSurfaces.end();
147 for (PlatformSurfaceMap::iterator iter = m_platformSurfaces.begin(); iter != end; ++iter) {
148 RefPtr<PlatformSurfaceInfo> platformSurfaceInfo = iter->second;
149 if (platformSurfaceInfo->m_tileID == tileID) {
150 platformSurfaceId = platformSurfaceInfo->m_SharedPlatformSurfaceTizen->id();
154 if (platformSurfaceId)
155 freePlatformSurface(platformSurfaceId);
158 void PlatformSurfacePoolTizen::freePlatformSurface(int platformSurfaceId)
160 RefPtr<PlatformSurfaceInfo> platformSurfaceInfo = m_platformSurfaces.get(platformSurfaceId);
161 if (platformSurfaceInfo && platformSurfaceInfo->m_used)
162 m_platformSurfacesToFree.append(platformSurfaceInfo);
164 LOG(TiledAC, "WARNING: no matching or freed PlatformSurfaceInfo for %d at [%s]", platformSurfaceId, __PRETTY_FUNCTION__);
167 void PlatformSurfacePoolTizen::freePlatformSurfacesIfNeeded()
169 if (m_platformSurfacesToFree.isEmpty())
172 for (size_t index = 0; index < m_platformSurfacesToFree.size(); index++) {
173 RefPtr<PlatformSurfaceInfo> platformSurfaceInfo = m_platformSurfacesToFree[index];
174 platformSurfaceInfo->m_SharedPlatformSurfaceTizen->lockSurface();
175 platformSurfaceInfo->m_SharedPlatformSurfaceTizen->unlockSurface();
176 platformSurfaceInfo->m_tileID = 0;
177 platformSurfaceInfo->m_used = false;
178 m_usedSizeInByte -= platformSurfaceInfo->sizeInByte();
181 LOG(TiledAC, "free platformSurface(%dx%d) XPlatformSurface pool size : %u MB (%u tiles) used : %u MB (%u tiles) at [%s]",
182 platformSurfaceInfo->m_SharedPlatformSurfaceTizen->size().width(),platformSurfaceInfo->m_SharedPlatformSurfaceTizen->size().height(),
183 m_sizeInByte/MB, m_platformSurfaces.size(), m_usedSizeInByte/MB, m_usedSizeInCount, __PRETTY_FUNCTION__);
186 m_platformSurfacesToFree.clear();
188 if (reachLowPoolUtilization(m_usedSizeInByte, m_sizeInByte))
192 void PlatformSurfacePoolTizen::removePlatformSurface(int platformSurfaceId)
194 /*FIXME : platformSurfaceId must not be zero.
195 But sometimes zero id was added to platformSurfaceMap.
196 If this problem is fixed, it will be removed.*/
197 if (!platformSurfaceId)
200 PlatformSurfaceMap::iterator foundSurface = m_platformSurfaces.find(platformSurfaceId);
201 if (foundSurface == m_platformSurfaces.end())
204 if (foundSurface->second->m_used) {
205 m_platformSurfacesIdToRemove.append(platformSurfaceId);
206 foundSurface->second->m_willBeRemoved = true;
207 startRemovePlaformSurfaceTimer();
211 int width = foundSurface->second->m_SharedPlatformSurfaceTizen->size().width();
212 int height = foundSurface->second->m_SharedPlatformSurfaceTizen->size().height();
215 m_sizeInByte -= foundSurface->second->sizeInByte();
216 m_platformSurfaces.remove(foundSurface);
218 LOG(TiledAC, "remove platformSurface(%dx%d) XPlatformSurface pool size : %u MB (%u tiles) used : %u MB (%u tiles) at [%s]",
219 width, height, m_sizeInByte/MB, m_platformSurfaces.size(), m_usedSizeInByte/MB, m_usedSizeInCount, "PlatformSurfacePoolTizen::removePlatformSurface");
222 void PlatformSurfacePoolTizen::willRemovePlatformSurface(int platformSurfaceId)
224 WebProcess::shared().connection()->send(Messages::WebProcessProxy::RemovePlatformSurfaceTextureFromPool(platformSurfaceId), 0);
227 bool PlatformSurfacePoolTizen::canCreatePlatformSurface()
229 if (m_sizeInByte >= m_maxSizeInByte)
232 return m_sizeInByte < m_maxSizeInByte;
235 RefPtr<PlatformSurfacePoolTizen::PlatformSurfaceInfo> PlatformSurfacePoolTizen::createPlatformSurface(const IntSize& size)
237 RefPtr<PlatformSurfaceInfo> newPlatformSurface = adoptRef(new PlatformSurfaceInfo(size));
238 if (!newPlatformSurface->m_SharedPlatformSurfaceTizen)
241 m_platformSurfaces.add(newPlatformSurface->m_SharedPlatformSurfaceTizen->id(), newPlatformSurface);
242 m_sizeInByte += newPlatformSurface->sizeInByte();
244 return newPlatformSurface.get();
247 void PlatformSurfacePoolTizen::shrink()
249 Vector<int> platformSurfacesToRemove;
251 size_t sizeInByte = m_sizeInByte;
252 PlatformSurfaceMap::iterator end = m_platformSurfaces.end();
253 for (PlatformSurfaceMap::iterator iter = m_platformSurfaces.begin(); iter != end; ++iter) {
254 RefPtr<PlatformSurfaceInfo> platformSurfaceInfo = iter->second;
256 if (!platformSurfaceInfo->m_used && ++platformSurfaceInfo->m_age > 3) {
257 platformSurfacesToRemove.append(platformSurfaceInfo->m_SharedPlatformSurfaceTizen->id());
258 sizeInByte -= platformSurfaceInfo->sizeInByte();
261 if (reachLowPoolUtilization(m_usedSizeInByte, m_sizeInByte)
262 && reachLowPoolUtilization(sizeInByte, m_sizeInByte))
267 if (platformSurfacesToRemove.size())
268 LOG(TiledAC, "remove %d platformSurfaces @PlatformSurfacePoolTizen::shrink", platformSurfacesToRemove.size());
270 for (size_t index = 0; index < platformSurfacesToRemove.size(); index++) {
271 // FIXME: we should send willRemovePlatformSurface to UIProcess before destroying xplatformSurface itself
272 // to make sure UIProcess release corresponding texture first.
273 // But currently there's no harm to destroying xplatformSurface first, because UIProcess will not use
274 // corresponding texture any longer and will successfully release the texture.
275 // Without removing platformSurfaces immediately here, we will encounter starvation of xplatformSurface too often.
276 removePlatformSurface(platformSurfacesToRemove[index]);
277 willRemovePlatformSurface(platformSurfacesToRemove[index]);
281 void PlatformSurfacePoolTizen::startRemovePlaformSurfaceTimer()
283 if (m_removePlaformSurfaceTimer.isActive())
285 m_removePlaformSurfaceTimer.startOneShot(0.01);
288 void PlatformSurfacePoolTizen::removePlaformSurfaceTimerFired(Timer<PlatformSurfacePoolTizen>*)
290 freePlatformSurfacesIfNeeded();
291 removePlatformSurfacesIfNeeded();
294 void PlatformSurfacePoolTizen::removePlatformSurfacesIfNeeded()
296 Vector<int> platformSurfacesIdToRemove = m_platformSurfacesIdToRemove;
297 m_platformSurfacesIdToRemove.clear();
299 for (Vector<int>::iterator iter = platformSurfacesIdToRemove.begin(); iter != platformSurfacesIdToRemove.end(); ++iter)
300 removePlatformSurface(*iter);