From 1ff1e5a9df16dbe995807fbb4ee2b85862b6660b Mon Sep 17 00:00:00 2001 From: sunbees Date: Sat, 7 Sep 2024 14:37:31 +0800 Subject: [PATCH] add fence sync for xcomponent-texture Signed-off-by: sunbees Change-Id: I77b53742f17fc57176895eaa016f83b3479f6988 --- .../pattern/xcomponent/xcomponent_pattern.cpp | 10 ++ .../pattern/xcomponent/xcomponent_pattern.h | 1 + .../render/adapter/rosen_render_surface.cpp | 136 ++++++++++++++---- .../render/adapter/rosen_render_surface.h | 21 +++ .../adapter/rosen_render_surface_mingw.cpp | 7 + .../components_ng/render/render_surface.h | 2 + .../pattern/web/mock_rosen_render_surface.cpp | 1 + 7 files changed, 148 insertions(+), 30 deletions(-) diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp index 6534ac09ccc..b259f2a0201 100644 --- a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.cpp @@ -225,8 +225,18 @@ void XComponentPattern::InitSurface() } renderSurface_->InitSurface(); renderSurface_->UpdateSurfaceConfig(); + if (type_ == XComponentType::TEXTURE) { + renderSurface_->RegisterBufferCallback(); + } surfaceId_ = renderSurface_->GetUniqueId(); + UpdateTransformHint(); +} + +void XComponentPattern::UpdateTransformHint() +{ + auto host = GetHost(); + CHECK_NULL_VOID(host); auto pipelineContext = host->GetContextRefPtr(); CHECK_NULL_VOID(pipelineContext); pipelineContext->AddWindowStateChangedCallback(host->GetId()); diff --git a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h index 91ad7229f89..13a32a10a40 100644 --- a/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h +++ b/frameworks/core/components_ng/pattern/xcomponent/xcomponent_pattern.h @@ -390,6 +390,7 @@ private: void UpdateAnalyzerOverlay(); void UpdateAnalyzerUIConfig(const RefPtr& geometryNode); void ReleaseImageAnalyzer(); + void UpdateTransformHint(); void SetRotation(uint32_t rotation); #ifdef RENDER_EXTRACT_SUPPORTED diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp index 509106cd0a7..0fd599a1187 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_render_surface.cpp @@ -16,6 +16,7 @@ #include "render_service_client/core/ui/rs_surface_node.h" #include "surface_utils.h" +#include "transaction/rs_interfaces.h" #include "base/log/dump_log.h" #include "core/common/ace_engine.h" #include "core/components_ng/render/adapter/rosen_render_context.h" @@ -69,22 +70,38 @@ struct SurfaceBufferNode { sptr buffer_; sptr fence_; OffsetF orgin_ { 0, 0 }; + uint32_t bufferId_ {}; + uint32_t sendTimes_ = 0; }; #endif RosenRenderSurface::~RosenRenderSurface() { if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) { surfaceDelegate_->ReleaseSurface(); - } else { - if (nativeWindow_) { - DestoryNativeWindow(nativeWindow_); - nativeWindow_ = nullptr; - } - UnregisterSurface(); + return; + } + if (nativeWindow_) { + DestoryNativeWindow(nativeWindow_); + nativeWindow_ = nullptr; + } + UnregisterSurface(); + if (isTexture_) { + Rosen::RSInterfaces::GetInstance().UnregisterSurfaceBufferCallback(getpid(), GetUniqueIdNum()); + std::lock_guard lock(surfaceNodeMutex_); while (!availableBuffers_.empty()) { auto surfaceNode = availableBuffers_.front(); availableBuffers_.pop(); - consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + if (surfaceNode) { + consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + } + } + auto iter = availableBufferList_.begin(); + while (iter != availableBufferList_.end()) { + auto surfaceNode = *iter; + if (surfaceNode) { + consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + } + iter = availableBufferList_.erase(iter); } } } @@ -227,6 +244,14 @@ std::string RosenRenderSurface::GetUniqueId() const return std::to_string(producerSurface_->GetUniqueId()); } +uint64_t RosenRenderSurface::GetUniqueIdNum() const +{ + if (!producerSurface_) { + return 0; + } + return producerSurface_->GetUniqueId(); +} + void RosenRenderSurface::SetExtSurfaceBounds(int32_t left, int32_t top, int32_t width, int32_t height) { if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) { @@ -424,24 +449,22 @@ void RosenRenderSurface::ConsumeXComponentBuffer() OHOS::Rect damage; SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, fence, timestamp, damage); - if (surfaceErr != SURFACE_ERROR_OK) { + if (surfaceErr != SURFACE_ERROR_OK || !surfaceBuffer) { TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "XComponent cannot acquire buffer error = %{public}d", surfaceErr); return; } PostRenderOnlyTaskToUI(); - - std::shared_ptr surfaceNode = nullptr; + auto surfaceNode = std::make_shared(surfaceBuffer, fence, orgin_); + CHECK_NULL_VOID(surfaceNode); + surfaceNode->bufferId_ = surfaceBuffer->GetSeqNum(); { std::lock_guard lock(surfaceNodeMutex_); - if (availableBuffers_.size() >= MAX_BUFFER_SIZE) { - surfaceNode = availableBuffers_.front(); - availableBuffers_.pop(); - surfaceErr = consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); - if (surfaceErr != SURFACE_ERROR_OK) { - TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "XComponent release buffer error = %{public}d", surfaceErr); - } + auto lastSurfaceNode = availableBufferList_.back(); + if (lastSurfaceNode && lastSurfaceNode->sendTimes_ <= 0) { + consumerSurface_->ReleaseBuffer(lastSurfaceNode->buffer_, SyncFence::INVALID_FENCE); + availableBufferList_.pop_back(); } - availableBuffers_.push(std::make_shared(surfaceBuffer, fence, orgin_)); + availableBufferList_.emplace_back(surfaceNode); } #endif } @@ -454,11 +477,15 @@ void RosenRenderSurface::ReleaseSurfaceBuffers() CHECK_NULL_VOID(consumerSurface_); { std::lock_guard lock(surfaceNodeMutex_); - while (availableBuffers_.size() > 1) { - auto surfaceNode = availableBuffers_.front(); - availableBuffers_.pop(); - if (surfaceNode) { - consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + if (!availableBufferList_.empty()) { + auto iter = availableBufferList_.begin(); + auto lastIter = std::prev(availableBufferList_.end()); + while (iter != lastIter) { + auto surfaceNode = *iter; + if (surfaceNode) { + consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + } + iter = availableBufferList_.erase(iter); } } } @@ -476,13 +503,14 @@ void RosenRenderSurface::DrawBufferForXComponent( { std::lock_guard lock(surfaceNodeMutex_); - if (!availableBuffers_.empty()) { - surfaceNode = availableBuffers_.back(); + if (!availableBufferList_.empty()) { + surfaceNode = availableBufferList_.back(); } - } - if (!surfaceNode) { - TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "surfaceNode is null"); - return; + if (!surfaceNode) { + TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "surfaceNode is null"); + return; + } + ++surfaceNode->sendTimes_; } ACE_SCOPED_TRACE("XComponent DrawBuffer"); #ifndef USE_ROSEN_DRAWING @@ -498,7 +526,7 @@ void RosenRenderSurface::DrawBufferForXComponent( #else auto& recordingCanvas = static_cast(canvas); Rosen::DrawingSurfaceBufferInfo info { surfaceNode->buffer_, offsetX, offsetY, static_cast(width), - static_cast(height) }; + static_cast(height), getpid(), GetUniqueIdNum() }; recordingCanvas.DrawSurfaceBuffer(info); #endif CHECK_NULL_VOID(recordingCanvas.GetDrawCmdList()); @@ -507,6 +535,40 @@ void RosenRenderSurface::DrawBufferForXComponent( #endif } +void RosenRenderSurface::RegisterBufferCallback() +{ +#ifdef OHOS_PLATFORM + CHECK_EQUAL_VOID(isTexture_, false); + auto pid = getpid(); + auto uid = GetUniqueIdNum(); + if (!bufferCallback_) { + bufferCallback_ = std::make_shared(WeakClaim(this)); + } + Rosen::RSInterfaces::GetInstance().RegisterSurfaceBufferCallback(pid, uid, bufferCallback_); +#endif +} + +void RosenRenderSurface::ReleaseSurfaceBufferById(uint32_t bufferId) +{ + std::lock_guard lock(surfaceNodeMutex_); + auto iter = availableBufferList_.begin(); + while (iter != availableBufferList_.end()) { + auto surfaceNode = *iter; + if (!surfaceNode) { + iter = availableBufferList_.erase(iter); + } else if (surfaceNode->bufferId_ == bufferId) { + // at least reserve one buffer + if (--surfaceNode->sendTimes_ <= 0 && (iter != std::prev(availableBufferList_.end()))) { + consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE); + availableBufferList_.erase(iter); + } + return; + } else { + ++iter; + } + } +} + void DrawBufferListener::OnBufferAvailable() { auto renderSurface = renderSurface_.Upgrade(); @@ -518,6 +580,20 @@ void DrawBufferListener::OnBufferAvailable() } } +#ifdef OHOS_PLATFORM +void XComponentSurfaceBufferCallback::OnFinish(uint64_t uid, const std::vector& surfaceBufferIds) +{ + auto renderSurface = renderSurface_.Upgrade(); + CHECK_NULL_VOID(renderSurface); + if (uid != renderSurface->GetUniqueIdNum()) { + return; + } + for (const auto& bufferId : surfaceBufferIds) { + renderSurface->ReleaseSurfaceBufferById(bufferId); + } +} +#endif + void ExtSurfaceCallback::OnSurfaceCreated(const sptr& /* surface */) { auto interface = weakInterface_.Upgrade(); diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_surface.h b/frameworks/core/components_ng/render/adapter/rosen_render_surface.h index 6ca2592a318..59e4634d877 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_surface.h +++ b/frameworks/core/components_ng/render/adapter/rosen_render_surface.h @@ -22,6 +22,7 @@ #include "surface.h" #include "surface_delegate.h" #include "surface/window.h" +#include "transaction/rs_render_service_client.h" #endif #include "base/memory/referenced.h" @@ -60,6 +61,8 @@ public: std::string GetUniqueId() const override; + uint64_t GetUniqueIdNum() const; + void SetIsTexture(bool isTexture) override { isTexture_ = isTexture; @@ -139,6 +142,10 @@ public: void DumpInfo() override; + void ReleaseSurfaceBufferById(uint32_t bufferId); + + void RegisterBufferCallback() override; + private: void PostRenderOnlyTaskToUI(); @@ -155,6 +162,8 @@ private: struct NativeWindow* nativeWindow_ = nullptr; sptr surfaceDelegate_; std::queue> availableBuffers_; + std::list> availableBufferList_; + std::shared_ptr bufferCallback_; int32_t failTimes_ = 0; #endif WeakPtr renderContext_ = nullptr; @@ -172,6 +181,18 @@ public: ~DrawBufferListener() override = default; void OnBufferAvailable() override; +private: + WeakPtr renderSurface_; +}; + +class XComponentSurfaceBufferCallback : public Rosen::SurfaceBufferCallback { +public: + explicit XComponentSurfaceBufferCallback(const WeakPtr& renderSurface) + : renderSurface_(renderSurface) + {} + virtual ~XComponentSurfaceBufferCallback() = default; + void OnFinish(uint64_t uid, const std::vector& surfaceBufferIds) override; + private: WeakPtr renderSurface_; }; diff --git a/frameworks/core/components_ng/render/adapter/rosen_render_surface_mingw.cpp b/frameworks/core/components_ng/render/adapter/rosen_render_surface_mingw.cpp index 2eba1163958..8cc93967752 100644 --- a/frameworks/core/components_ng/render/adapter/rosen_render_surface_mingw.cpp +++ b/frameworks/core/components_ng/render/adapter/rosen_render_surface_mingw.cpp @@ -103,4 +103,11 @@ void RosenRenderSurface::Connect() const {} void RosenRenderSurface::Disconnect() const {} +uint64_t RosenRenderSurface::GetUniqueIdNum() const +{ + return 0; +} + +void RosenRenderSurface::RegisterBufferCallback() {} + } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/render/render_surface.h b/frameworks/core/components_ng/render/render_surface.h index dc5d6ef3093..7152881d530 100644 --- a/frameworks/core/components_ng/render/render_surface.h +++ b/frameworks/core/components_ng/render/render_surface.h @@ -132,6 +132,8 @@ public: virtual void Disconnect() const {}; + virtual void RegisterBufferCallback() {} + protected: ACE_DISALLOW_COPY_AND_MOVE(RenderSurface); }; diff --git a/test/unittest/core/pattern/web/mock_rosen_render_surface.cpp b/test/unittest/core/pattern/web/mock_rosen_render_surface.cpp index 43c8a8d6f64..30e339770d6 100644 --- a/test/unittest/core/pattern/web/mock_rosen_render_surface.cpp +++ b/test/unittest/core/pattern/web/mock_rosen_render_surface.cpp @@ -42,4 +42,5 @@ namespace OHOS::Ace::NG { void RosenRenderSurface::UnregisterSurface() const {} void RosenRenderSurface::Connect() const {} void RosenRenderSurface::Disconnect() const {} + void RosenRenderSurface::RegisterBufferCallback() {} } -- Gitee