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