diff --git a/interfaces/inner_api/surface/surface_buffer.h b/interfaces/inner_api/surface/surface_buffer.h index a6b7f829be1493db1674586a967d32f2e83daddd..986c984fdb3e59d975f701ccc5b7b6c13c675db4 100644 --- a/interfaces/inner_api/surface/surface_buffer.h +++ b/interfaces/inner_api/surface/surface_buffer.h @@ -126,6 +126,10 @@ public: { return SCALING_MODE_SCALE_TO_WINDOW; } + virtual void RegisterDeleteBufferCallback(const std::function& callback) const + { + (void)callback; + } protected: SurfaceBuffer() {} SurfaceBuffer(const SurfaceBuffer&) = delete; @@ -134,7 +138,7 @@ protected: }; using OnReleaseFunc = std::function &)>; -using OnDeleteBufferFunc = std::function; +using OnDeleteBufferFunc = std::function; using OnReleaseFuncWithFence = std::function&, const sptr&)>; using OnUserDataChangeFunc = std::function; } // namespace OHOS diff --git a/surface/BUILD.gn b/surface/BUILD.gn index 6cae8e965610aee01f43bfd9801e26aa0d1a7d09..696ce98e6446d5138174377649f6adc3d665a2dd 100644 --- a/surface/BUILD.gn +++ b/surface/BUILD.gn @@ -76,6 +76,7 @@ ohos_shared_library("surface") { "src/buffer_utils.cpp", "src/consumer_surface.cpp", "src/consumer_surface_delegator.cpp", + "src/image_cache_cleaner.cpp", "src/metadata_helper.cpp", "src/native_buffer.cpp", "src/native_window.cpp", diff --git a/surface/include/buffer_queue.h b/surface/include/buffer_queue.h index 0ba5b034eb1133055c9cc695e4821b48163e045b..51a4be159becee1e37cc7ef552ca6b9dd56e510a 100644 --- a/surface/include/buffer_queue.h +++ b/surface/include/buffer_queue.h @@ -215,7 +215,6 @@ private: GSError AttachBufferUpdateStatus(std::unique_lock &lock, uint32_t sequence, int32_t timeOut); void AttachBufferUpdateBufferInfo(sptr& buffer); void ListenerBufferReleasedCb(sptr &buffer, const sptr &fence); - void OnBufferDeleteCbForHardwareThreadLocked(const sptr &buffer) const; GSError CheckBufferQueueCache(uint32_t sequence); GSError ReallocBufferLocked(const BufferRequestConfig &config, struct IBufferProducer::RequestBufferReturnValue &retval); @@ -258,8 +257,6 @@ private: OnReleaseFunc onBufferRelease_ = nullptr; std::mutex onBufferReleaseMutex_; sptr producerListener_ = nullptr; - OnDeleteBufferFunc onBufferDeleteForRSMainThread_; - OnDeleteBufferFunc onBufferDeleteForRSHardwareThread_; std::condition_variable waitReqCon_; std::condition_variable waitAttachCon_; sptr tunnelHandle_ = nullptr; diff --git a/surface/include/image_cache_cleaner.h b/surface/include/image_cache_cleaner.h new file mode 100644 index 0000000000000000000000000000000000000000..d634d849c3dcb5ab31e5193558c81ce5a01cddda --- /dev/null +++ b/surface/include/image_cache_cleaner.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef IMAGE_CACHE_CLEANER_H +#define IMAGE_CACHE_CLEANER_H +#include +#include +#include +#include "sync_fence.h" + +namespace OHOS { +class ImageCacheCleaner { +public: + static ImageCacheCleaner& GetInstance(); + + /* + * @brief Set release fence for a specific buffer + * @param sequenceNumber The sequence number of the buffer + * @param releaseFence The release fence to be set + */ + void SetReleaseFence(uint32_t sequenceNumber, const sptr& releaseFence); + + /* + * @brief Clean cache immediately for the specified buffer + * @param sequenceNumber The sequence number of the buffer to be cleaned + */ + void CleanCache(uint32_t sequenceNumber); + + /* + * @brief Set callback function for cache cleanup + * @param callback The callback function to be called when cleaning cache + */ + void SetCleanupCallback(std::function callback, bool isForUniRedraw); + + ImageCacheCleaner(const ImageCacheCleaner&) = delete; + ImageCacheCleaner& operator=(const ImageCacheCleaner&) = delete; + +private: + ImageCacheCleaner() = default; + ~ImageCacheCleaner() = default; + + std::mutex mutex_; + std::function cleanupCallback_; + std::function uniCleanupCallback_; + std::unordered_map> releaseFences_; +}; +} // namespace OHOS +#endif // IMAGE_CACHE_CLEANER_H \ No newline at end of file diff --git a/surface/include/surface_buffer_impl.h b/surface/include/surface_buffer_impl.h index d72615587add78559ec04eb20944f431ed68c9b4..e5e9826e9aa4b1c7dd0daaa96ccfe663737169f6 100644 --- a/surface/include/surface_buffer_impl.h +++ b/surface/include/surface_buffer_impl.h @@ -20,6 +20,7 @@ #include #include #include +#include "sync_fence.h" #include "egl_data.h" #include "native_buffer.h" #include "stdint.h" @@ -90,6 +91,7 @@ public: void SetSurfaceBufferScalingMode(const ScalingMode &scalingMode) override; ScalingMode GetSurfaceBufferScalingMode() const override; + void RegisterDeleteBufferCallback(const std::function& callback) const override; private: void FreeBufferHandleLocked(); bool MetaDataCachedLocked(const uint32_t key, const std::vector& value); diff --git a/surface/src/buffer_queue.cpp b/surface/src/buffer_queue.cpp index 2e59f7884c5b43943292ca86d572e5661082679d..fe656379fc9e53e84ccb0d99001b888e4b50acc6 100644 --- a/surface/src/buffer_queue.cpp +++ b/surface/src/buffer_queue.cpp @@ -27,6 +27,7 @@ #include "buffer_log.h" #include "hebc_white_list.h" #include "hitrace_meter.h" +#include "image_cache_cleaner.h" #include "metadata_helper.h" #include "sandbox_utils.h" #include "surface_buffer_impl.h" @@ -94,14 +95,6 @@ BufferQueue::BufferQueue(const std::string &name) BufferQueue::~BufferQueue() { BLOGD("~BufferQueue dtor, uniqueId: %{public}" PRIu64 ".", uniqueId_); - for (auto &[id, _] : bufferQueueCache_) { - if (onBufferDeleteForRSMainThread_ != nullptr) { - onBufferDeleteForRSMainThread_(id); - } - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - onBufferDeleteForRSHardwareThread_(id); - } - } } uint32_t BufferQueue::GetUsedSize() @@ -917,15 +910,6 @@ void BufferQueue::ListenerBufferReleasedCb(sptr &buffer, const sp buffer->GetSeqNum(), uniqueId_); } } - std::lock_guard lockGuard(mutex_); - OnBufferDeleteCbForHardwareThreadLocked(buffer); -} - -void BufferQueue::OnBufferDeleteCbForHardwareThreadLocked(const sptr &buffer) const -{ - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - onBufferDeleteForRSHardwareThread_(buffer->GetSeqNum()); - } } GSError BufferQueue::ReleaseBuffer(sptr &buffer, const sptr& fence) @@ -935,13 +919,13 @@ GSError BufferQueue::ReleaseBuffer(sptr &buffer, const sptrGetSeqNum(); + ImageCacheCleaner::GetInstance().SetReleaseFence(sequence, fence); SURFACE_TRACE_NAME_FMT("ReleaseBuffer name: %s queueId: %" PRIu64 " seq: %u", name_.c_str(), uniqueId_, sequence); { std::lock_guard lockGuard(mutex_); if (bufferQueueCache_.find(sequence) == bufferQueueCache_.end()) { SURFACE_TRACE_NAME_FMT("buffer not found in cache"); BLOGE("cache not find the buffer(%{public}u), uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); - OnBufferDeleteCbForHardwareThreadLocked(buffer); return SURFACE_ERROR_BUFFER_NOT_INCACHE; } @@ -1018,12 +1002,6 @@ void BufferQueue::DeleteBufferInCache(uint32_t sequence) { auto it = bufferQueueCache_.find(sequence); if (it != bufferQueueCache_.end()) { - if (onBufferDeleteForRSMainThread_ != nullptr) { - onBufferDeleteForRSMainThread_(sequence); - } - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - onBufferDeleteForRSHardwareThread_(sequence); - } BLOGD("DeleteBufferInCache seq: %{public}u, uniqueId: %{public}" PRIu64 ".", sequence, uniqueId_); bufferQueueCache_.erase(it); deletingList_.push_back(sequence); @@ -1244,12 +1222,6 @@ GSError BufferQueue::DetachBuffer(sptr &buffer) bufferQueueCache_[sequence].state, sequence, uniqueId_); return GSERROR_NO_ENTRY; } - if (onBufferDeleteForRSMainThread_ != nullptr) { - onBufferDeleteForRSMainThread_(sequence); - } - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - onBufferDeleteForRSHardwareThread_(sequence); - } bufferQueueCache_.erase(sequence); return GSERROR_OK; } @@ -1354,18 +1326,9 @@ GSError BufferQueue::UnRegisterProducerReleaseListener() GSError BufferQueue::RegisterDeleteBufferListener(OnDeleteBufferFunc func, bool isForUniRedraw) { - std::lock_guard lockGuard(mutex_); - if (isForUniRedraw) { - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - return GSERROR_OK; - } - onBufferDeleteForRSHardwareThread_ = func; - } else { - if (onBufferDeleteForRSMainThread_ != nullptr) { - return GSERROR_OK; - } - onBufferDeleteForRSMainThread_ = func; - } + (void)func; + (void)isForUniRedraw; + // ImageCacheCleaner::GetInstance().SetCleanupCallback(func, isForUniRedraw); return GSERROR_OK; } @@ -1413,19 +1376,6 @@ uint64_t BufferQueue::GetDefaultUsage() void BufferQueue::ClearLocked() { - for (auto &[id, ele] : bufferQueueCache_) { - if (onBufferDeleteForRSMainThread_ != nullptr) { - onBufferDeleteForRSMainThread_(id); - } - if (onBufferDeleteForRSHardwareThread_ != nullptr) { - onBufferDeleteForRSHardwareThread_(id); - } - - if (name_ == "RosenWeb") { - BLOGD("ClearLocked, bufferFd: %{public}d, refCount: %{public}d.", - ele.buffer->GetBufferHandle()->fd, ele.buffer->GetSptrRefCount()); - } - } bufferQueueCache_.clear(); freeList_.clear(); dirtyList_.clear(); diff --git a/surface/src/image_cache_cleaner.cpp b/surface/src/image_cache_cleaner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..67c2f3c0142d908f5f25626a609454e8e2903718 --- /dev/null +++ b/surface/src/image_cache_cleaner.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "image_cache_cleaner.h" + +namespace OHOS { + +namespace { +constexpr int32_t WAIT_FENCE_TIME_OUT = 3000; // 3000ms +} + +ImageCacheCleaner& ImageCacheCleaner::GetInstance() +{ + static ImageCacheCleaner instance; + return instance; +} + +void ImageCacheCleaner::SetReleaseFence(uint32_t sequenceNumber, const sptr& releaseFence) +{ + if (releaseFence == nullptr || !releaseFence->IsValid()) { + return; + } + + std::lock_guard lock(mutex_); + releaseFences_[sequenceNumber] = releaseFence; +} + +void ImageCacheCleaner::CleanCache(uint32_t sequenceNumber) +{ + sptr fence; + std::function cleanupCopy; + std::function uniCleanupCopy; + + { + std::lock_guard lock(mutex_); + auto it = releaseFences_.find(sequenceNumber); + if (it != releaseFences_.end()) { + fence = it->second; + releaseFences_.erase(it); + } + cleanupCopy = cleanupCallback_; + uniCleanupCopy = uniCleanupCallback_; + } + + // Wait for release fence if it exists + if (fence != nullptr && fence->IsValid()) { + fence->Wait(WAIT_FENCE_TIME_OUT); + } + + // Execute callbacks outside the lock + if (cleanupCopy) { + cleanupCopy(sequenceNumber); + } + if (uniCleanupCopy) { + uniCleanupCopy(sequenceNumber); + } +} + +void ImageCacheCleaner::SetCleanupCallback(std::function callback, bool isForUniRedraw) +{ + std::lock_guard lock(mutex_); + if (isForUniRedraw) { + uniCleanupCallback_ = std::move(callback); + } else { + cleanupCallback_ = std::move(callback); + } +} + +} // namespace OHOS \ No newline at end of file diff --git a/surface/src/surface_buffer_impl.cpp b/surface/src/surface_buffer_impl.cpp index 2bdd5d5d88f047d115e3fda0a14a4608fde5418f..3e9270fb39024ff8a0d561bbfa44f90770a3ac6d 100644 --- a/surface/src/surface_buffer_impl.cpp +++ b/surface/src/surface_buffer_impl.cpp @@ -23,6 +23,7 @@ #include #include "buffer_log.h" #include "buffer_extra_data_impl.h" +#include "image_cache_cleaner.h" #include "v1_1/buffer_handle_meta_key_type.h" #include "v1_2/display_buffer_type.h" #include "v1_2/include/idisplay_buffer.h" @@ -112,9 +113,15 @@ SurfaceBufferImpl::SurfaceBufferImpl(uint32_t seqNum) SurfaceBufferImpl::~SurfaceBufferImpl() { BLOGD("~SurfaceBufferImpl dtor, seq: %{public}u", sequenceNumber_); + ImageCacheCleaner::GetInstance().CleanCache(sequenceNumber_); FreeBufferHandleLocked(); } +void SurfaceBufferImpl::RegisterDeleteBufferCallback(const std::function& callback) const +{ + ImageCacheCleaner::GetInstance().SetCleanupCallback(callback, true); +} + bool SurfaceBufferImpl::MetaDataCachedLocked(const uint32_t key, const std::vector& value) { auto iter = metaDataCache_.find(key);