• 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 "cache_data.h"
17 #include <cerrno>
18 #include <chrono>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <cstring>
22 #include <securec.h>
23 #include "render_context_log.h"
24 #ifdef PRELOAD_SHADER_CACHE
25 #include "shader_cache_utils.h"
26 #endif
27 
28 namespace OHOS {
29 const char* RS_CACHE_MAGIC_HEAD = "OHRS";
30 const int RS_CACHE_MAGIC_HEAD_LEN = 4;
31 const int RS_CACHE_HEAD_LEN = 8;
32 const int RS_BYTE_SIZE = 8;
33 const int SHADER_CACHE_CLEAR_LEVEL = 2;
34 const int CHECK_FRAME_FREQUENCY = 10;
35 namespace Rosen {
CacheData(const size_t maxKeySize,const size_t maxValueSize,const size_t maxTotalSize,const std::string & fileName)36 CacheData::CacheData(const size_t maxKeySize, const size_t maxValueSize,
37     const size_t maxTotalSize, const std::string& fileName)
38     : maxKeySize_(maxKeySize),
39     maxValueSize_(maxValueSize),
40     maxTotalSize_(maxTotalSize),
41     cacheDir_(fileName)
42 {
43     softLimit_ = static_cast<size_t>(SHADER_CACHE_SOFT_LIMIT * maxTotalSize);
44 }
45 
~CacheData()46 CacheData::~CacheData() {}
47 
CrcGen(const uint8_t * buffer,size_t bufferSize)48 uint32_t CacheData::CrcGen(const uint8_t *buffer, size_t bufferSize)
49 {
50     const uint32_t polynoimal = 0xEDB88320;
51     uint32_t crc = 0xFFFFFFFF;
52 
53     for (size_t i = 0; i < bufferSize ; ++i) {
54         crc ^= (static_cast<uint32_t>(buffer[i]));
55         for (size_t j = 0; j < RS_BYTE_SIZE; ++j) {
56             if (crc & 0x01) {
57                 crc = (crc >> 1) ^ polynoimal;
58             } else {
59                 crc >>= 1;
60             }
61         }
62     }
63     return crc ^ 0xFFFFFFFF;
64 }
65 
IsValidFile(uint8_t * buffer,size_t bufferSize)66 bool CacheData::IsValidFile(uint8_t *buffer, size_t bufferSize)
67 {
68     if (memcmp(buffer, RS_CACHE_MAGIC_HEAD, RS_CACHE_MAGIC_HEAD_LEN) != 0) {
69         LOGE("abandon, because of mismatched RS_CACHE_MAGIC_HEAD");
70         return false;
71     }
72 
73     uint32_t* storedCrc = reinterpret_cast<uint32_t*>(buffer + RS_CACHE_MAGIC_HEAD_LEN);
74     uint32_t computedCrc = CrcGen(buffer + RS_CACHE_HEAD_LEN, bufferSize - RS_CACHE_HEAD_LEN);
75     if (computedCrc != *storedCrc) {
76         LOGE("abandon, because of mismatched crc code");
77         DumpAbnormalCacheToFile(buffer, bufferSize);
78         return false;
79     }
80 
81     return true;
82 }
83 
DumpAbnormalCacheToFile(uint8_t * buffer,size_t bufferSize)84 void CacheData::DumpAbnormalCacheToFile(uint8_t *buffer, size_t bufferSize)
85 {
86     if (cacheDir_.length() <= 0) {
87         LOGE("dump abnormal cache failed, because of empty filename");
88         return;
89     }
90     char canonicalPath[PATH_MAX] = {0};
91     if (realpath(cacheDir_.c_str(), canonicalPath) == nullptr) {
92         LOGE("dump abnormal cache failed, because of realpath check");
93         return;
94     }
95     std::string abnormalCacheDir = canonicalPath;
96     abnormalCacheDir = abnormalCacheDir + "_abnormal";
97     int fd = open(abnormalCacheDir.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
98     if (fd == ERR_NUMBER) {
99         if (errno == EEXIST) {
100             if (unlink(abnormalCacheDir.c_str()) == ERR_NUMBER) {
101                 LOGE("dump abnormal cache failed, because unlinking the existing file fails");
102                 return;
103             }
104             fd = open(abnormalCacheDir.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
105         }
106         if (fd == ERR_NUMBER) {
107             LOGE("dump abnormal cache failed, because the file creation fails");
108             return;
109         }
110     }
111     fdsan_exchange_owner_tag(fd, 0, LOG_DOMAIN);
112 
113     std::time_t curTime = time(nullptr);
114     char timestamp[TIME_MAX_LEN] = {0};
115     std::strftime(timestamp, TIME_MAX_LEN, "%Y-%m-%d %H:%M:%S", std::localtime(&curTime));
116     if (write(fd, timestamp, TIME_MAX_LEN) == ERR_NUMBER) {
117         LOGE("dump abnormal cache failed, because fail to write timestamp to disk");
118         fdsan_close_with_tag(fd, LOG_DOMAIN);
119         unlink(abnormalCacheDir.c_str());
120         return;
121     }
122 
123     if (write(fd, buffer, bufferSize) == ERR_NUMBER) {
124         LOGE("dump abnormal cache failed, because fail to write data to disk");
125         fdsan_close_with_tag(fd, LOG_DOMAIN);
126         unlink(abnormalCacheDir.c_str());
127         return;
128     }
129     fchmod(fd, S_IRUSR);
130     fdsan_close_with_tag(fd, LOG_DOMAIN);
131     return;
132 }
133 
CacheReadFromFile(const std::string filePath)134 void CacheData::CacheReadFromFile(const std::string filePath)
135 {
136     if (filePath.length() <= 0) {
137         LOGD("abandon, because of empty filename.");
138         return;
139     }
140 
141     int fd = open(filePath.c_str(), O_RDONLY, 0);
142     if (fd == ERR_NUMBER) {
143         if (errno != ENOENT) {
144             LOGD("abandon, because fail to open file");
145         }
146         return;
147     }
148     fdsan_exchange_owner_tag(fd, 0, LOG_DOMAIN);
149     struct stat statBuf;
150     if (fstat(fd, &statBuf) == ERR_NUMBER) {
151         LOGD("abandon, because fail to get the file status");
152         fdsan_close_with_tag(fd, LOG_DOMAIN);
153         return;
154     }
155     if (statBuf.st_size < 0) {
156         LOGD("abandon, negative file size");
157         fdsan_close_with_tag(fd, LOG_DOMAIN);
158         return;
159     }
160 
161     size_t fileSize = static_cast<size_t>(statBuf.st_size);
162     if (fileSize < RS_CACHE_HEAD_LEN || fileSize > maxTotalSize_ * maxMultipleSize_ + RS_CACHE_HEAD_LEN) {
163         LOGE("abandon, illegal file size");
164         fdsan_close_with_tag(fd, LOG_DOMAIN);
165         return;
166     }
167     uint8_t *buffer = reinterpret_cast<uint8_t*>(mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE, fd, 0));
168     if (buffer == MAP_FAILED) {
169         LOGD("abandon, because of mmap failure:");
170         fdsan_close_with_tag(fd, LOG_DOMAIN);
171         return;
172     }
173 
174     if (!IsValidFile(buffer, fileSize)) {
175         LOGE("abandon, invalid file");
176         munmap(buffer, fileSize);
177         fdsan_close_with_tag(fd, LOG_DOMAIN);
178         return;
179     }
180 
181     uint8_t *shaderBuffer = reinterpret_cast<uint8_t*>(buffer + RS_CACHE_HEAD_LEN);
182     if (DeSerialize(shaderBuffer, fileSize - RS_CACHE_HEAD_LEN) < 0) {
183         LOGE("abandon, because fail to read file contents");
184     }
185     munmap(buffer, fileSize);
186     fdsan_close_with_tag(fd, LOG_DOMAIN);
187 }
188 
ReadFromFile()189 void CacheData::ReadFromFile()
190 {
191 #ifdef PRELOAD_SHADER_CACHE
192     // read cache from preload cache dir
193     CacheReadFromFile(ShaderCacheUtils::GetPreloadCacheDir());
194 #endif
195     // read cache from user data dir
196     CacheReadFromFile(cacheDir_);
197 }
198 
WriteToFile()199 void CacheData::WriteToFile()
200 {
201     if (cacheDir_.length() <= 0) {
202         LOGD("abandon, because of empty filename.");
203         return;
204     }
205     int fd = open(cacheDir_.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
206     if (fd == ERR_NUMBER) {
207         if (errno == EEXIST) {
208             if (unlink(cacheDir_.c_str()) == ERR_NUMBER) {
209                 LOGD("abandon, because unlinking the existing file fails");
210                 return;
211             }
212             fd = open(cacheDir_.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
213         }
214         if (fd == ERR_NUMBER) {
215             LOGD("abandon, because the file creation fails");
216             return;
217         }
218     }
219     fdsan_exchange_owner_tag(fd, 0, LOG_DOMAIN);
220     size_t cacheSize = SerializedSize();
221     if (cacheSize <= 0) {
222         LOGD("abandon, illegal serialized size");
223         fdsan_close_with_tag(fd, LOG_DOMAIN);
224         return;
225     }
226     size_t bufferSize = cacheSize + RS_CACHE_HEAD_LEN;
227     uint8_t *buffer = new uint8_t[bufferSize];
228     if (!buffer) {
229         LOGD("abandon, because fail to allocate buffer for cache content");
230         fdsan_close_with_tag(fd, LOG_DOMAIN);
231         unlink(cacheDir_.c_str());
232         return;
233     }
234     if (Serialize(buffer + RS_CACHE_HEAD_LEN, cacheSize) < 0) {
235         LOGD("abandon, because fail to serialize the CacheData:");
236         delete[] buffer;
237         fdsan_close_with_tag(fd, LOG_DOMAIN);
238         unlink(cacheDir_.c_str());
239         return;
240     }
241 
242     // Write the file rs magic head and CRC code
243     if (memcpy_s(buffer, bufferSize, RS_CACHE_MAGIC_HEAD, RS_CACHE_MAGIC_HEAD_LEN) != 0) {
244         delete[] buffer;
245         fdsan_close_with_tag(fd, LOG_DOMAIN);
246         return;
247     }
248     uint32_t *crc = reinterpret_cast<uint32_t*>(buffer + RS_CACHE_MAGIC_HEAD_LEN);
249     *crc = CrcGen(buffer + RS_CACHE_HEAD_LEN, cacheSize);
250 
251     if (write(fd, buffer, bufferSize) == ERR_NUMBER) {
252         LOGD("abandon, because fail to write to disk");
253         delete[] buffer;
254         fdsan_close_with_tag(fd, LOG_DOMAIN);
255         unlink(cacheDir_.c_str());
256         return;
257     }
258     delete[] buffer;
259     fchmod(fd, S_IRUSR);
260     fdsan_close_with_tag(fd, LOG_DOMAIN);
261 }
262 
Rewrite(const void * key,const size_t keySize,const void * value,const size_t valueSize)263 void CacheData::Rewrite(const void *key, const size_t keySize, const void *value, const size_t valueSize)
264 {
265     if (maxKeySize_ < keySize || maxValueSize_ < valueSize ||
266         maxTotalSize_ < keySize + valueSize || keySize == 0 || valueSize <= 0) {
267         LOGD("abandon, because of illegal content size");
268         return;
269     }
270     std::shared_ptr<DataPointer> fakeDataPointer(std::make_shared<DataPointer>(key, keySize, false));
271     ShaderPointer fakeShaderPointer(fakeDataPointer, nullptr);
272     bool isShaderFound = false;
273     size_t newTotalSize = 0;
274     while (!isShaderFound) {
275         auto index = std::lower_bound(shaderPointers_.begin(), shaderPointers_.end(), fakeShaderPointer);
276         if (index == shaderPointers_.end() || fakeShaderPointer < *index) {
277             std::shared_ptr<DataPointer> keyPointer(std::make_shared<DataPointer>(key, keySize, true));
278             std::shared_ptr<DataPointer> valuePointer(std::make_shared<DataPointer>(value, valueSize, true));
279             newTotalSize = totalSize_ + keySize + valueSize;
280             if (IfSizeValidate(newTotalSize, keySize + valueSize)) {
281                 shaderPointers_.insert(index, ShaderPointer(keyPointer, valuePointer));
282                 totalSize_ = newTotalSize;
283                 break;
284             }
285             if (IfSkipClean(keySize + valueSize)) {
286                 break;
287             }
288             if (IfCleanFinished()) {
289                 continue;
290             }
291             break;
292         } else {
293             std::shared_ptr<DataPointer> valuePointer(std::make_shared<DataPointer>(value, valueSize, true));
294             std::shared_ptr<DataPointer> oldValuePointer(index->GetValuePointer());
295             newTotalSize = totalSize_ + valueSize - oldValuePointer->GetSize();
296             size_t addedSize = (valueSize > oldValuePointer->GetSize()) ? valueSize - oldValuePointer->GetSize() : 0;
297             if (IfSizeValidate(newTotalSize, addedSize)) {
298                 index->SetValue(valuePointer);
299                 totalSize_ = newTotalSize;
300                 break;
301             }
302             if (IfSkipClean(addedSize)) {
303                 break;
304             }
305             if (IfCleanFinished()) {
306                 continue;
307             }
308             break;
309         }
310         isShaderFound = true;
311     }
312     cleanThreshold_ = 0;
313 }
314 
Get(const void * key,const size_t keySize,void * value,const size_t valueSize)315 std::tuple<CacheData::ErrorCode, size_t> CacheData::Get(const void *key, const size_t keySize,
316     void *value, const size_t valueSize)
317 {
318     if (maxKeySize_ < keySize) {
319         LOGD("abandon, because the key is too large");
320         return {ErrorCode::VALUE_SIZE_OVER_MAX_SIZE, 0};
321     }
322     std::shared_ptr<DataPointer> fakeDataPointer(std::make_shared<DataPointer>(key, keySize, false));
323     ShaderPointer fakeShaderPointer(fakeDataPointer, nullptr);
324     auto index = std::lower_bound(shaderPointers_.begin(), shaderPointers_.end(), fakeShaderPointer);
325     if (index == shaderPointers_.end() || fakeShaderPointer < *index) {
326         LOGD("abandon, because no key is found");
327         return {ErrorCode::KEY_NOT_FOUND, 0};
328     }
329     std::shared_ptr <DataPointer> valuePointer(index->GetValuePointer());
330     size_t valuePointerSize = valuePointer->GetSize();
331     if (valuePointerSize > valueSize) {
332         LOGD("abandon, because of insufficient buffer space");
333         return {ErrorCode::VALUE_SIZE_TOO_SAMLL, valuePointerSize};
334     }
335     if (memcpy_s(value, valueSize, valuePointer->GetData(), valuePointerSize)) {
336         LOGD("abandon, failed to copy content");
337         return {ErrorCode::COPY_FAILED, 0};
338     }
339     return {ErrorCode::NO_ERR, valuePointerSize};
340 }
341 
SerializedSize() const342 size_t CacheData::SerializedSize() const
343 {
344     size_t size = Align4(sizeof(Header));
345     for (const ShaderPointer &p: shaderPointers_) {
346         std::shared_ptr <DataPointer> const &keyPointer = p.GetKeyPointer();
347         std::shared_ptr <DataPointer> const &valuePointer = p.GetValuePointer();
348         size += Align4(sizeof(ShaderData) + keyPointer->GetSize() + valuePointer->GetSize());
349     }
350     return size;
351 }
352 
Serialize(uint8_t * buffer,const size_t size) const353 int CacheData::Serialize(uint8_t *buffer, const size_t size) const
354 {
355     if (size < sizeof(Header)) {
356         LOGD("abandon because of insufficient buffer space.");
357         return -EINVAL;
358     }
359     Header *header = reinterpret_cast<Header *>(buffer);
360     header->numShaders_ = shaderPointers_.size();
361     size_t byteOffset = Align4(sizeof(Header));
362     size_t headSize = sizeof(ShaderData);
363 
364     uint8_t *byteBuffer = reinterpret_cast<uint8_t *>(buffer);
365     for (const ShaderPointer &p: shaderPointers_) {
366         std::shared_ptr<DataPointer> const &keyPointer = p.GetKeyPointer();
367         std::shared_ptr<DataPointer> const &valuePointer = p.GetValuePointer();
368         size_t keySize = keyPointer->GetSize();
369         size_t valueSize = valuePointer->GetSize();
370         size_t pairSize = sizeof(ShaderData) + keySize + valueSize;
371         size_t alignedSize = Align4(pairSize);
372         if (byteOffset + alignedSize > size) {
373             LOGD("abandon because of insufficient buffer space.");
374             return -EINVAL;
375         }
376 
377         ShaderData *shaderBuffer = reinterpret_cast<ShaderData *>(&byteBuffer[byteOffset]);
378         shaderBuffer->keySize_ = keySize;
379         shaderBuffer->valueSize_ = valueSize;
380         size_t sizeLeft = size - byteOffset - headSize;
381         if (memcpy_s(shaderBuffer->data_, sizeLeft, keyPointer->GetData(), keySize)) {
382             LOGD("abandon, failed to copy key");
383             return -EINVAL;
384         }
385         if (memcpy_s(shaderBuffer->data_ + keySize, sizeLeft - keySize, valuePointer->GetData(), valueSize)) {
386             LOGD("abandon, failed to copy value");
387             return -EINVAL;
388         }
389         if (alignedSize > pairSize) {
390             auto ret = memset_s(shaderBuffer->data_ + keySize + valueSize, alignedSize - pairSize, 0,
391                 alignedSize - pairSize);
392             if (ret != EOK) {
393                 LOGD("abandon, failed to memset_s");
394                 return -EINVAL;
395             }
396         }
397         byteOffset += alignedSize;
398     }
399     return 0;
400 }
401 
DeSerialize(uint8_t const * buffer,const size_t size)402 int CacheData::DeSerialize(uint8_t const *buffer, const size_t size)
403 {
404     if (size < sizeof(Header)) {
405         LOGD("abandon, not enough room for cache header");
406     }
407 
408     if (buffer == nullptr) {
409         LOGD("abandon, buffer is null");
410         return -EINVAL;
411     }
412     const Header *header = reinterpret_cast<const Header *>(buffer);
413     size_t numShaders = header->numShaders_;
414     size_t byteOffset = Align4(sizeof(Header));
415 
416     const uint8_t *byteBuffer = reinterpret_cast<const uint8_t *>(buffer);
417     for (size_t i = 0; i < numShaders; i++) {
418         if (byteOffset + sizeof(ShaderData) > size) {
419             shaderPointers_.clear();
420             LOGD("abandon because of insufficient buffer space");
421             return -EINVAL;
422         }
423         const ShaderData *shaderBuffer = reinterpret_cast<const ShaderData *>(&byteBuffer[byteOffset]);
424         size_t keySize = shaderBuffer->keySize_;
425         size_t valueSize = shaderBuffer->valueSize_;
426         size_t pairSize = sizeof(ShaderData) + keySize + valueSize;
427         size_t alignedSize = Align4(pairSize);
428         if (byteOffset + alignedSize > size) {
429             shaderPointers_.clear();
430             LOGD("abandon, not enough room for cache headers");
431             return -EINVAL;
432         }
433 
434         const uint8_t *data = shaderBuffer->data_;
435         Rewrite(data, keySize, data + keySize, valueSize);
436         byteOffset += alignedSize;
437     }
438     return 0;
439 }
440 
IfSizeValidate(const size_t newSize,const size_t addedSize) const441 bool CacheData::IfSizeValidate(const size_t newSize, const size_t addedSize) const
442 {
443     // check if size is ok and we don't neet to clean the shaders
444     if (newSize <= maxTotalSize_ || addedSize == 0) {
445         return true;
446     }
447     return false;
448 }
449 
IfSkipClean(const size_t addedSize) const450 bool CacheData::IfSkipClean(const size_t addedSize) const
451 {
452     // check if the new shader is still too large after cleaning
453     size_t maxPermittedSize = maxTotalSize_ - maxTotalSize_ / cleanLevel_;
454     if (addedSize > maxPermittedSize) {
455         LOGD("new shader is too large, abandon insert");
456         return true;
457     }
458     return false;
459 }
460 
IfCleanFinished()461 bool CacheData::IfCleanFinished()
462 {
463     if (!cleanThreshold_) {
464         RandClean(maxTotalSize_ / cleanLevel_);
465         return true;
466     } else {
467         LOGD("abandon, failed to clean the shaders");
468         return false;
469     }
470 }
471 
RandClean(const size_t cleanThreshold)472 void CacheData::RandClean(const size_t cleanThreshold)
473 {
474     if (cleanThreshold == 0) {
475         LOGD("CleanThreshold must be > 0");
476         return;
477     }
478     if (cleanThreshold_ == 0) {
479         if (!CleanInit()) {
480             return;
481         }
482     }
483     cleanThreshold_ = cleanThreshold;
484 
485     while (totalSize_ > cleanThreshold_) {
486         if (!StepClean()) {
487             break;
488         }
489     }
490 }
491 
CleanInit()492 bool CacheData::CleanInit()
493 {
494     auto now = std::chrono::steady_clock::now().time_since_epoch().count();
495     if (now < 0) {
496         LOGD("abandon, illegal negative now value");
497         return false;
498     }
499     unsigned long currentTime = static_cast<unsigned long>(now);
500     for (int indexRand = 0; indexRand < randLength_; ++indexRand) {
501         cleanInit_[indexRand] = (currentTime >> (indexRand * randShift_)) & 0xFFFF;
502     }
503     return true;
504 }
505 
StepClean()506 bool CacheData::StepClean()
507 {
508     long int randIndex = nrand48(cleanInit_);
509     if (randIndex < 0) {
510         LOGD("abandon, illegal negative randIndex value");
511         return false;
512     }
513     size_t sizeRandIndex = static_cast<size_t>(randIndex);
514     size_t currentSize = shaderPointers_.size();
515     if (currentSize == 0) {
516         LOGD("abandon, shader is empty, nothing to clean");
517         return false;
518     }
519     size_t removeIndex = sizeRandIndex % (currentSize);
520     if (!Clean(removeIndex)) {
521         LOGD("abandon, cleaned nothing");
522         return false;
523     }
524     return true;
525 }
526 
Clean(const size_t removeIndex)527 size_t CacheData::Clean(const size_t removeIndex)
528 {
529     if (removeIndex >= shaderPointers_.size()) {
530         LOGD("illegal shader index, abandon cleaning");
531         return 0;
532     }
533     const ShaderPointer &shader(shaderPointers_[removeIndex]);
534     size_t reducedSize = shader.GetKeyPointer()->GetSize() + shader.GetValuePointer()->GetSize();
535     totalSize_ -= reducedSize;
536     shaderPointers_.erase(shaderPointers_.begin() + removeIndex);
537     return reducedSize;
538 }
539 
CheckShaderCacheOverSoftLimit() const540 bool CacheData::CheckShaderCacheOverSoftLimit() const
541 {
542     return totalSize_ >= softLimit_;
543 }
544 
PurgeShaderCacheAfterAnimate(const std::function<bool (void)> & nextFrameHasArrived)545 void CacheData::PurgeShaderCacheAfterAnimate(const std::function<bool(void)>& nextFrameHasArrived)
546 {
547     if (!CleanInit()) {
548         return;
549     }
550     if (!nextFrameHasArrived) {
551         LOGD("nextFrame Func is Empty");
552         return;
553     }
554     const size_t cleanTarget = maxTotalSize_ / SHADER_CACHE_CLEAR_LEVEL;
555     int cleanTimes = 0;
556     while (totalSize_ > cleanTarget && (cleanTimes % CHECK_FRAME_FREQUENCY != 0 || !nextFrameHasArrived())) {
557         if (!StepClean()) {
558             break;
559         }
560         cleanTimes++;
561     }
562 }
563 
DataPointer(const void * data,size_t size,bool ifOccupy)564 CacheData::DataPointer::DataPointer(const void *data, size_t size, bool ifOccupy)
565     : pointer_(nullptr),
566     size_(size),
567     toFree_(ifOccupy)
568 {
569     if (ifOccupy) {
570         pointer_ = malloc(size);
571     } else {
572         pointer_ = data;
573     }
574 
575     if (data != nullptr && ifOccupy) {
576         if (memcpy_s(const_cast<void *>(pointer_), size, data, size)) {
577             LOGD("abandon: failed to copy data");
578             return;
579         }
580     }
581 }
582 
~DataPointer()583 CacheData::DataPointer::~DataPointer()
584 {
585     if (toFree_) {
586         free(const_cast<void *>(pointer_));
587         pointer_ = nullptr;
588     }
589 }
590 
ShaderPointer()591 CacheData::ShaderPointer::ShaderPointer() {}
592 
ShaderPointer(const std::shared_ptr<DataPointer> & key,const std::shared_ptr<DataPointer> & value)593 CacheData::ShaderPointer::ShaderPointer(const std::shared_ptr <DataPointer> &key,
594                                         const std::shared_ptr <DataPointer> &value)
595     : keyPointer_(key),
596     valuePointer_(value) {}
597 
ShaderPointer(const ShaderPointer & sp)598 CacheData::ShaderPointer::ShaderPointer(const ShaderPointer &sp)
599     : keyPointer_(sp.keyPointer_),
600     valuePointer_(sp.valuePointer_) {}
601 }   // namespace Rosen
602 }   // namespace OHOS