• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "memory/rs_memory_snapshot.h"
17 #include "render/rs_image_cache.h"
18 #include "pixel_map.h"
19 
20 namespace OHOS {
21 namespace Rosen {
22 // modify the RSImageCache instance as global to extend life cycle, fix destructor crash
23 static RSImageCache gRSImageCacheInstance;
24 
Instance()25 RSImageCache& RSImageCache::Instance()
26 {
27     return gRSImageCacheInstance;
28 }
29 
CacheDrawingImage(uint64_t uniqueId,std::shared_ptr<Drawing::Image> img)30 void RSImageCache::CacheDrawingImage(uint64_t uniqueId, std::shared_ptr<Drawing::Image> img)
31 {
32     if (img && uniqueId > 0) {
33         std::lock_guard<std::mutex> lock(mutex_);
34         drawingImageCache_.emplace(uniqueId, std::make_pair(img, 0));
35     }
36 }
37 
GetDrawingImageCache(uint64_t uniqueId) const38 std::shared_ptr<Drawing::Image> RSImageCache::GetDrawingImageCache(uint64_t uniqueId) const
39 {
40     std::lock_guard<std::mutex> lock(mutex_);
41     auto it = drawingImageCache_.find(uniqueId);
42     if (it != drawingImageCache_.end()) {
43         return it->second.first;
44     }
45     return nullptr;
46 }
47 
IncreaseDrawingImageCacheRefCount(uint64_t uniqueId)48 void RSImageCache::IncreaseDrawingImageCacheRefCount(uint64_t uniqueId)
49 {
50     std::lock_guard<std::mutex> lock(mutex_);
51     auto it = drawingImageCache_.find(uniqueId);
52     if (it != drawingImageCache_.end()) {
53         it->second.second++;
54     }
55 }
56 
ReleaseDrawingImageCache(uint64_t uniqueId)57 void RSImageCache::ReleaseDrawingImageCache(uint64_t uniqueId)
58 {
59     // release the Drawing::Image if no RSImage holds it
60     std::lock_guard<std::mutex> lock(mutex_);
61     auto it = drawingImageCache_.find(uniqueId);
62     if (it != drawingImageCache_.end()) {
63         it->second.second--;
64         if (it->second.first == nullptr || it->second.second == 0) {
65             drawingImageCache_.erase(it);
66         }
67     }
68 }
69 
CachePixelMap(uint64_t uniqueId,std::shared_ptr<Media::PixelMap> pixelMap)70 void RSImageCache::CachePixelMap(uint64_t uniqueId, std::shared_ptr<Media::PixelMap> pixelMap)
71 {
72     if (pixelMap && uniqueId > 0) {
73         {
74             std::lock_guard<std::mutex> lock(mutex_);
75             pixelMapCache_.emplace(uniqueId, std::make_pair(pixelMap, 0));
76         }
77         auto type = pixelMap->GetAllocatorType();
78         pid_t pid = uniqueId >> 32; // right shift 32 bit to restore pid
79         if (type != Media::AllocatorType::DMA_ALLOC && pid) {
80             auto realSize = type == Media::AllocatorType::SHARE_MEM_ALLOC
81                 ? pixelMap->GetCapacity() / 2 // rs only counts half of the SHARE_MEM_ALLOC memory
82                 : pixelMap->GetCapacity();
83             MemorySnapshot::Instance().AddCpuMemory(pid, realSize);
84         }
85     }
86 }
87 
GetPixelMapCache(uint64_t uniqueId) const88 std::shared_ptr<Media::PixelMap> RSImageCache::GetPixelMapCache(uint64_t uniqueId) const
89 {
90     std::lock_guard<std::mutex> lock(mutex_);
91     auto it = pixelMapCache_.find(uniqueId);
92     if (it != pixelMapCache_.end()) {
93         return it->second.first;
94     }
95     return nullptr;
96 }
97 
IncreasePixelMapCacheRefCount(uint64_t uniqueId)98 void RSImageCache::IncreasePixelMapCacheRefCount(uint64_t uniqueId)
99 {
100     std::lock_guard<std::mutex> lock(mutex_);
101     auto it = pixelMapCache_.find(uniqueId);
102     if (it != pixelMapCache_.end()) {
103         it->second.second++;
104     }
105 }
106 
CollectUniqueId(uint64_t uniqueId)107 void RSImageCache::CollectUniqueId(uint64_t uniqueId)
108 {
109     std::unique_lock<std::mutex> lock(uniqueIdListMutex_);
110     uniqueIdList_.push_back(uniqueId);
111 }
112 
ReleaseUniqueIdList()113 void RSImageCache::ReleaseUniqueIdList()
114 {
115     std::list<uint64_t> clearList;
116     {
117         std::unique_lock<std::mutex> lock(uniqueIdListMutex_);
118         uniqueIdList_.swap(clearList);
119     }
120     for (const auto& uniqueId : clearList) {
121         ReleasePixelMapCache(uniqueId);
122     }
123 }
124 
CheckUniqueIdIsEmpty()125 bool RSImageCache::CheckUniqueIdIsEmpty()
126 {
127     if (uniqueIdListMutex_.try_lock()) {
128         if (uniqueIdList_.empty()) {
129             uniqueIdListMutex_.unlock();
130             return true;
131         }
132         uniqueIdListMutex_.unlock();
133     }
134     return false;
135 }
136 
ReleasePixelMapCache(uint64_t uniqueId)137 void RSImageCache::ReleasePixelMapCache(uint64_t uniqueId)
138 {
139     std::shared_ptr<Media::PixelMap> pixelMap = nullptr;
140     {
141         // release the pixelMap if no RSImage holds it
142         std::lock_guard<std::mutex> lock(mutex_);
143         auto it = pixelMapCache_.find(uniqueId);
144         if (it != pixelMapCache_.end()) {
145             it->second.second--;
146             if (it->second.first == nullptr || it->second.second == 0) {
147                 pixelMap = it->second.first;
148                 bool shouldCount = pixelMap && pixelMap->GetAllocatorType() != Media::AllocatorType::DMA_ALLOC;
149                 pid_t pid = uniqueId >> 32; // right shift 32 bit to restore pid
150                 if (shouldCount && pid) {
151                     auto realSize = pixelMap->GetAllocatorType() == Media::AllocatorType::SHARE_MEM_ALLOC
152                         ? pixelMap->GetCapacity() / 2 // rs only counts half of the SHARE_MEM_ALLOC memory
153                         : pixelMap->GetCapacity();
154                     MemorySnapshot::Instance().RemoveCpuMemory(pid, realSize);
155                 }
156                 pixelMapCache_.erase(it);
157                 ReleaseDrawingImageCacheByPixelMapId(uniqueId);
158             }
159         } else {
160             ReleaseDrawingImageCacheByPixelMapId(uniqueId);
161         }
162     }
163     pixelMap.reset();
164 }
165 
CheckRefCntAndReleaseImageCache(uint64_t uniqueId,std::shared_ptr<Media::PixelMap> & pixelMapIn)166 bool RSImageCache::CheckRefCntAndReleaseImageCache(uint64_t uniqueId, std::shared_ptr<Media::PixelMap>& pixelMapIn)
167 {
168     if (!pixelMapIn) {
169         return false;
170     }
171     {
172         // release the pixelMap if no RSImage holds it
173         std::lock_guard<std::mutex> lock(mutex_);
174         auto it = pixelMapCache_.find(uniqueId);
175         if (it == pixelMapCache_.end()) {
176             return false;
177         }
178         if (it->second.first != pixelMapIn || it->second.second > 1) {
179             return false; // skip purge if pixelMap mismatch
180         }
181         ReleaseDrawingImageCacheByPixelMapId(uniqueId);
182     }
183     return true;
184 }
185 
CacheRenderDrawingImageByPixelMapId(uint64_t uniqueId,std::shared_ptr<Drawing::Image> img,pid_t tid)186 void RSImageCache::CacheRenderDrawingImageByPixelMapId(uint64_t uniqueId,
187     std::shared_ptr<Drawing::Image> img, pid_t tid)
188 {
189     if (uniqueId > 0 && img) {
190         std::lock_guard<std::mutex> lock(mapMutex_);
191         pixelMapIdRelatedDrawingImageCache_[uniqueId][tid] = img;
192     }
193 }
194 
GetRenderDrawingImageCacheByPixelMapId(uint64_t uniqueId,pid_t tid) const195 std::shared_ptr<Drawing::Image> RSImageCache::GetRenderDrawingImageCacheByPixelMapId(uint64_t uniqueId, pid_t tid) const
196 {
197     std::lock_guard<std::mutex> lock(mapMutex_);
198     auto it = pixelMapIdRelatedDrawingImageCache_.find(uniqueId);
199     if (it != pixelMapIdRelatedDrawingImageCache_.end()) {
200         auto innerIt = it->second.find(tid);
201         if (innerIt != it->second.end()) {
202             return innerIt->second;
203         }
204     }
205     return nullptr;
206 }
207 
ReleaseDrawingImageCacheByPixelMapId(uint64_t uniqueId)208 void RSImageCache::ReleaseDrawingImageCacheByPixelMapId(uint64_t uniqueId)
209 {
210     std::lock_guard<std::mutex> lock(mapMutex_);
211     auto it = pixelMapIdRelatedDrawingImageCache_.find(uniqueId);
212     if (it != pixelMapIdRelatedDrawingImageCache_.end()) {
213         pixelMapIdRelatedDrawingImageCache_.erase(it);
214     }
215 }
216 } // namespace Rosen
217 } // namespace OHOS
218