1 /*
2  * Copyright (c) 2022-2024 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 #include "core/components_ng/render/adapter/rosen_render_surface.h"
16 
17 #include "render_service_client/core/ui/rs_surface_node.h"
18 #include "surface_utils.h"
19 #include "transaction/rs_interfaces.h"
20 
21 #include "base/log/dump_log.h"
22 #include "core/common/ace_engine.h"
23 #include "core/components_ng/render/adapter/rosen_render_context.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 
26 namespace OHOS::Ace::NG {
27 #ifdef OHOS_PLATFORM
28 struct SurfaceBufferNode {
SurfaceBufferNodeOHOS::Ace::NG::SurfaceBufferNode29     SurfaceBufferNode(sptr<SurfaceBuffer> buf, sptr<SyncFence> fence, OffsetF orgin)
30         : buffer_(std::move(buf)), acquireFence_(std::move(fence)), orgin_(orgin)
31     {}
32     ~SurfaceBufferNode() noexcept = default;
33 
34     sptr<SurfaceBuffer> buffer_;
35     sptr<SyncFence> acquireFence_ = SyncFence::INVALID_FENCE;
36     sptr<SyncFence> releaseFence_ = SyncFence::INVALID_FENCE;
37     OffsetF orgin_ { 0, 0 };
38     uint32_t bufferId_ {};
39     uint32_t sendTimes_ = 0;
40 };
41 #endif
42 
43 namespace {
44 const char* const SURFACE_STRIDE_ALIGNMENT = "8";
45 constexpr int32_t EXT_SURFACE_DEFAULT_SIZE = 1;
46 constexpr int32_t MAX_BUFFER_SIZE = 3;
47 const std::string PATTERN_TYPE_WEB = "WEBPATTERN";
48 const uint32_t ADJUST_WEB_DRAW_LENGTH = 3000;
49 const uint32_t DEFAULT_WEB_DRAW_LENGTH = 6167;
50 const std::string SURFACE_WIDTH = "surface_width";
51 const std::string SURFACE_HEIGHT = "surface_height";
52 const int32_t SIZE_LIMIT = 5999;
53 const int32_t PERMITTED_DIFFERENCE = 100;
54 const int32_t FAILED_LIMIT = 3;
55 const int32_t WAIT_FENCE_TIME = 5000;
56 
ConvertRotation(uint32_t rotation)57 GraphicTransformType ConvertRotation(uint32_t rotation)
58 {
59     GraphicTransformType transform = GraphicTransformType::GRAPHIC_ROTATE_BUTT;
60     switch (rotation) {
61         case 0:
62             transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
63             break;
64         case 90:
65             transform = GraphicTransformType::GRAPHIC_ROTATE_90;
66             break;
67         case 180:
68             transform = GraphicTransformType::GRAPHIC_ROTATE_180;
69             break;
70         case 270:
71             transform = GraphicTransformType::GRAPHIC_ROTATE_270;
72             break;
73         default:
74             transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
75             break;
76     }
77     return transform;
78 }
79 
ReleaseAllBuffers(std::list<std::shared_ptr<SurfaceBufferNode>> & bufferList,const OHOS::sptr<IConsumerSurface> & consumerSurface)80 void ReleaseAllBuffers(
81     std::list<std::shared_ptr<SurfaceBufferNode>>& bufferList, const OHOS::sptr<IConsumerSurface>& consumerSurface)
82 {
83     for (const auto& surfaceNode : bufferList) {
84         if (surfaceNode) {
85             consumerSurface->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
86         }
87     }
88     bufferList.clear();
89 }
90 
ReleaseAllButLastBuffer(std::list<std::shared_ptr<SurfaceBufferNode>> & bufferList,const OHOS::sptr<IConsumerSurface> & consumerSurface)91 void ReleaseAllButLastBuffer(
92     std::list<std::shared_ptr<SurfaceBufferNode>>& bufferList, const OHOS::sptr<IConsumerSurface>& consumerSurface)
93 {
94     auto iter = bufferList.begin();
95     while (bufferList.size() > 1) {
96         auto surfaceNode = *iter;
97         if (surfaceNode) {
98             consumerSurface->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
99         }
100         iter = bufferList.erase(iter);
101     }
102 }
103 } // namespace
104 
~RosenRenderSurface()105 RosenRenderSurface::~RosenRenderSurface()
106 {
107     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
108         surfaceDelegate_->ReleaseSurface();
109         return;
110     }
111     if (nativeWindow_) {
112         DestoryNativeWindow(nativeWindow_);
113         nativeWindow_ = nullptr;
114     }
115     UnregisterSurface();
116     if (isTexture_) {
117         Rosen::RSInterfaces::GetInstance().UnregisterSurfaceBufferCallback(getpid(), GetUniqueIdNum());
118         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
119         while (!availableBuffers_.empty()) {
120             auto surfaceNode = availableBuffers_.front();
121             availableBuffers_.pop();
122             if (surfaceNode) {
123                 consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE);
124             }
125         }
126         ReleaseAllBuffers(buffersToDraw_, consumerSurface_);
127         ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
128     }
129 }
130 
InitSurface()131 void RosenRenderSurface::InitSurface()
132 {
133     auto renderContext = renderContext_.Upgrade();
134     if (!renderContext && SystemProperties::GetExtSurfaceEnabled()) {
135         auto context = PipelineContext::GetCurrentContext();
136         CHECK_NULL_VOID(context);
137         auto windowId = context->GetWindowId();
138         surfaceDelegate_ = new OHOS::SurfaceDelegate(windowId);
139         surfaceDelegate_->CreateSurface();
140         if (extSurfaceCallbackInterface_) {
141             surfaceDelegate_->AddSurfaceCallback(new ExtSurfaceCallback(extSurfaceCallbackInterface_));
142         } else {
143             surfaceDelegate_->SetBounds(0, 0, EXT_SURFACE_DEFAULT_SIZE, EXT_SURFACE_DEFAULT_SIZE);
144         }
145         producerSurface_ = surfaceDelegate_->GetSurface();
146     } else {
147         CHECK_NULL_VOID(renderContext);
148         auto rosenRenderContext = AceType::DynamicCast<NG::RosenRenderContext>(renderContext);
149         CHECK_NULL_VOID(rosenRenderContext);
150         auto rsNode = rosenRenderContext->GetRSNode();
151         CHECK_NULL_VOID(rsNode);
152         if (isTexture_) {
153             rsNode->SetFrameGravity(OHOS::Rosen::Gravity::RESIZE);
154             consumerSurface_ = IConsumerSurface::Create();
155             if (consumerSurface_ == nullptr) {
156                 return;
157             }
158             sptr<IBufferProducer> producer = consumerSurface_->GetProducer();
159             if (producer == nullptr) {
160                 return;
161             }
162             producerSurface_ = Surface::CreateSurfaceAsProducer(producer);
163             if (producerSurface_ == nullptr) {
164                 return;
165             }
166             if (drawBufferListener_ == nullptr) {
167                 drawBufferListener_ = new DrawBufferListener(WeakClaim(this));
168             }
169             consumerSurface_->RegisterConsumerListener(drawBufferListener_);
170         } else {
171             auto surfaceNode = OHOS::Rosen::RSBaseNode::ReinterpretCast<OHOS::Rosen::RSSurfaceNode>(rsNode);
172             CHECK_NULL_VOID(surfaceNode);
173             producerSurface_ = surfaceNode->GetSurface();
174         }
175     }
176     RegisterSurface();
177 }
178 
Connect() const179 void RosenRenderSurface::Connect() const
180 {
181     CHECK_NULL_VOID(producerSurface_);
182     producerSurface_->Connect();
183 }
184 
Disconnect() const185 void RosenRenderSurface::Disconnect() const
186 {
187     CHECK_NULL_VOID(producerSurface_);
188     producerSurface_->Disconnect();
189 }
190 
RegisterSurface() const191 void RosenRenderSurface::RegisterSurface() const
192 {
193     CHECK_NULL_VOID(producerSurface_);
194     auto* surfaceUtils = SurfaceUtils::GetInstance();
195     CHECK_NULL_VOID(surfaceUtils);
196     auto ret = surfaceUtils->Add(producerSurface_->GetUniqueId(), producerSurface_);
197     if (ret != SurfaceError::SURFACE_ERROR_OK) {
198         LOGE("add surface error: %{public}d", ret);
199     }
200 }
201 
UnregisterSurface() const202 void RosenRenderSurface::UnregisterSurface() const
203 {
204     CHECK_NULL_VOID(producerSurface_);
205     auto* surfaceUtils = SurfaceUtils::GetInstance();
206     CHECK_NULL_VOID(surfaceUtils);
207     auto ret = surfaceUtils->Remove(producerSurface_->GetUniqueId());
208     if (ret != SurfaceError::SURFACE_ERROR_OK) {
209         LOGE("remove surface error: %{public}d", ret);
210     }
211 }
212 
UpdateSurfaceConfig()213 void RosenRenderSurface::UpdateSurfaceConfig()
214 {
215     CHECK_NULL_VOID(producerSurface_);
216     producerSurface_->SetQueueSize(queueSize_);
217     producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", SURFACE_STRIDE_ALIGNMENT);
218     producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(GRAPHIC_PIXEL_FMT_RGBA_8888));
219 }
220 
GetNativeWindow()221 void* RosenRenderSurface::GetNativeWindow()
222 {
223     return nativeWindow_;
224 }
225 
SetRenderContext(const RefPtr<RenderContext> & renderContext)226 void RosenRenderSurface::SetRenderContext(const RefPtr<RenderContext>& renderContext)
227 {
228     renderContext_ = WeakClaim(RawPtr(renderContext));
229 }
230 
ConfigSurface(uint32_t surfaceWidth,uint32_t surfaceHeight)231 void RosenRenderSurface::ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight)
232 {
233     CHECK_NULL_VOID(producerSurface_);
234     producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(surfaceWidth));
235     producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(surfaceHeight));
236 }
237 
IsSurfaceValid() const238 bool RosenRenderSurface::IsSurfaceValid() const
239 {
240     return producerSurface_ != nullptr;
241 }
242 
CreateNativeWindow()243 void RosenRenderSurface::CreateNativeWindow()
244 {
245     nativeWindow_ = CreateNativeWindowFromSurface(&producerSurface_);
246 }
247 
AdjustNativeWindowSize(uint32_t width,uint32_t height)248 void RosenRenderSurface::AdjustNativeWindowSize(uint32_t width, uint32_t height)
249 {
250     CHECK_NULL_VOID(nativeWindow_);
251     NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width, height);
252 }
253 
UpdateSurfaceSizeInUserData(uint32_t width,uint32_t height)254 void RosenRenderSurface::UpdateSurfaceSizeInUserData(uint32_t width, uint32_t height)
255 {
256     CHECK_NULL_VOID(producerSurface_);
257     producerSurface_->SetUserData(SURFACE_WIDTH, std::to_string(width));
258     producerSurface_->SetUserData(SURFACE_HEIGHT, std::to_string(height));
259 }
260 
GetUniqueId() const261 std::string RosenRenderSurface::GetUniqueId() const
262 {
263     if (!producerSurface_) {
264         return "";
265     }
266     return std::to_string(producerSurface_->GetUniqueId());
267 }
268 
GetUniqueIdNum() const269 uint64_t RosenRenderSurface::GetUniqueIdNum() const
270 {
271     if (!producerSurface_) {
272         return 0;
273     }
274     return producerSurface_->GetUniqueId();
275 }
276 
SetExtSurfaceBounds(int32_t left,int32_t top,int32_t width,int32_t height)277 void RosenRenderSurface::SetExtSurfaceBounds(int32_t left, int32_t top, int32_t width, int32_t height)
278 {
279     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
280         surfaceDelegate_->SetBounds(left, top, width, height);
281     }
282 }
283 
SetExtSurfaceCallback(const RefPtr<ExtSurfaceCallbackInterface> & extSurfaceCallback)284 void RosenRenderSurface::SetExtSurfaceCallback(const RefPtr<ExtSurfaceCallbackInterface>& extSurfaceCallback)
285 {
286     extSurfaceCallbackInterface_ = extSurfaceCallback;
287 }
288 
SetTransformHint(uint32_t rotation)289 void RosenRenderSurface::SetTransformHint(uint32_t rotation)
290 {
291     auto transform = ConvertRotation(rotation);
292     CHECK_NULL_VOID(producerSurface_);
293     producerSurface_->SetTransformHint(transform);
294 }
295 
DumpInfo()296 void RosenRenderSurface::DumpInfo()
297 {
298     DumpLog::GetInstance().AddDesc(
299         std::string("UserData[surface_width]: ")
300             .append(producerSurface_ ? producerSurface_->GetUserData(SURFACE_WIDTH) : "NoSurface"));
301     DumpLog::GetInstance().AddDesc(
302         std::string("UserData[surface_height]: ")
303             .append(producerSurface_ ? producerSurface_->GetUserData(SURFACE_HEIGHT) : "NoSurface"));
304 }
305 
SetSurfaceDefaultSize(int32_t width,int32_t height)306 void RosenRenderSurface::SetSurfaceDefaultSize(int32_t width, int32_t height)
307 {
308     if (consumerSurface_) {
309         consumerSurface_->SetDefaultWidthAndHeight(width, height);
310     }
311 }
312 
DrawBuffer(int32_t width,int32_t height)313 void RosenRenderSurface::DrawBuffer(int32_t width, int32_t height)
314 {
315 #ifdef OHOS_PLATFORM
316     auto renderContext = renderContext_.Upgrade();
317     CHECK_NULL_VOID(renderContext);
318     auto rosenRenderContext = DynamicCast<RosenRenderContext>(renderContext);
319     CHECK_NULL_VOID(rosenRenderContext);
320     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
321     {
322         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
323 
324         if (availableBuffers_.size() >= 1) {
325             surfaceNode = availableBuffers_.back();
326         }
327     }
328     if (!surfaceNode) {
329         return;
330     }
331     bool res = CompareBufferSize(width, height, surfaceNode);
332     ACE_SCOPED_TRACE("Web DrawBuffer");
333     if (res && isNeedSyncGeometryProperties_) {
334         RectF keyBoardAvoidRect = RectF(keyBoardAvoidRect_.GetX(), keyBoardAvoidRect_.GetY(), width, height);
335         ACE_SCOPED_TRACE("Web DrawBuffer, SyncGeometryProperties: %s", keyBoardAvoidRect.ToString().c_str());
336         rosenRenderContext->SyncGeometryProperties(keyBoardAvoidRect);
337         isNeedSyncGeometryProperties_ = false;
338     }
339     rosenRenderContext->StartRecording();
340     auto rsNode = rosenRenderContext->GetRSNode();
341     CHECK_NULL_VOID(rsNode);
342     rsNode->DrawOnNode(
343 #ifndef USE_ROSEN_DRAWING
344         Rosen::RSModifierType::CONTENT_STYLE, [surfaceNode](const std::shared_ptr<SkCanvas>& canvas) {
345             CHECK_NULL_VOID(canvas);
346             Rosen::RSSurfaceBufferInfo info { surfaceNode->buffer_, surfaceNode->orgin_.GetX(),
347                 surfaceNode->orgin_.GetY(), surfaceNode->buffer_->GetSurfaceBufferWidth(),
348                 surfaceNode->buffer_->GetSurfaceBufferHeight() };
349             auto* recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas.get());
350             CHECK_NULL_VOID(recordingCanvas);
351             recordingCanvas->DrawSurfaceBuffer(info);
352 #else
353         Rosen::RSModifierType::CONTENT_STYLE,
354         [surfaceNode](const std::shared_ptr<RSCanvas>& canvas) {
355             CHECK_NULL_VOID(canvas);
356             Rosen::DrawingSurfaceBufferInfo info { surfaceNode->buffer_, surfaceNode->orgin_.GetX(),
357                 surfaceNode->orgin_.GetY(), surfaceNode->buffer_->GetSurfaceBufferWidth(),
358                 surfaceNode->buffer_->GetSurfaceBufferHeight() };
359             auto* recordingCanvas = static_cast<RSRecordingCanvas*>(canvas.get());
360             CHECK_NULL_VOID(recordingCanvas);
361             recordingCanvas->DrawSurfaceBuffer(info);
362 #endif
363         });
364     rosenRenderContext->StopRecordingIfNeeded();
365 #endif
366 }
367 
368 #ifdef OHOS_PLATFORM
369 bool RosenRenderSurface::CompareBufferSize(
370     int32_t width, int32_t height, std::shared_ptr<SurfaceBufferNode> surfaceNode)
371 {
372     int32_t bufferWidth = surfaceNode->buffer_->GetSurfaceBufferWidth();
373     int32_t bufferHeight = surfaceNode->buffer_->GetSurfaceBufferHeight();
374     auto pipeline = AceType::DynamicCast<NG::PipelineContext>(PipelineBase::GetCurrentContext());
375 
376     if (bufferWidth > SIZE_LIMIT || bufferHeight > SIZE_LIMIT
377         || (abs(height - bufferHeight) < PERMITTED_DIFFERENCE && abs(width - bufferWidth) < PERMITTED_DIFFERENCE)) {
378         failTimes_ = 0;
379     } else {
380         failTimes_++;
381         if (failTimes_ <= FAILED_LIMIT) {
382             pipeline->SetIsFreezeFlushMessage(true);
383             ACE_SCOPED_TRACE("Web SetIsFreezeFlushMessage (width %d, height %d, bufferWidth %d, bufferHeight %d)",
384                 width, height, bufferWidth, bufferHeight);
385             return false;
386         }
387     }
388     return true;
389 }
390 #endif
391 
392 void RosenRenderSurface::ConsumeWebBuffer()
393 {
394 #ifdef OHOS_PLATFORM
395     ContainerScope scope(instanceId_);
396     CHECK_NULL_VOID(consumerSurface_);
397 
398     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
399     sptr<SyncFence> fence = SyncFence::INVALID_FENCE;
400     int64_t timestamp = 0;
401     OHOS::Rect damage;
402 
403     SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, fence, timestamp, damage);
404     if (surfaceErr != SURFACE_ERROR_OK) {
405         LOGE("cannot acquire buffer error = %{public}d", surfaceErr);
406         return;
407     }
408     CHECK_NULL_VOID(fence);
409     auto errorCode = fence->Wait(WAIT_FENCE_TIME);
410     LOGD("RosenRenderSurface::ConsumeWebBuffer, wait Fence ,errorCode : %{public}d", errorCode);
411     PostRenderOnlyTaskToUI();
412 
413     int32_t bufferWidth = surfaceBuffer->GetSurfaceBufferWidth();
414     int32_t bufferHeight = surfaceBuffer->GetSurfaceBufferHeight();
415     if (axis_ == Axis::VERTICAL) {
416         if (webOffset_ >= 0 || bufferHeight < ADJUST_WEB_DRAW_LENGTH * 2 || bufferHeight >= DEFAULT_WEB_DRAW_LENGTH) {
417             orgin_.SetY(0);
418         } else {
419             int32_t stepStear = bufferHeight - ADJUST_WEB_DRAW_LENGTH * 2;
420             orgin_.SetY(stepStear * ADJUST_WEB_DRAW_LENGTH);
421         }
422     } else if (axis_ == Axis::HORIZONTAL) {
423         if (webOffset_ >= 0 || bufferWidth < ADJUST_WEB_DRAW_LENGTH * 2 || bufferWidth >= DEFAULT_WEB_DRAW_LENGTH) {
424             orgin_.SetX(0);
425         } else {
426             int32_t stepStear = bufferWidth - ADJUST_WEB_DRAW_LENGTH * 2;
427             orgin_.SetX(stepStear * ADJUST_WEB_DRAW_LENGTH);
428         }
429     }
430     LOGD("ConsumeWebBuffer x : %{public}f, y : %{public}f, width : %{public}d, height : %{public}d",
431         orgin_.GetX(), orgin_.GetY(), bufferWidth, bufferHeight);
432     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
433     {
434         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
435         if (availableBuffers_.size() >= MAX_BUFFER_SIZE) {
436             surfaceNode = availableBuffers_.front();
437             availableBuffers_.pop();
438             consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE);
439         }
440         availableBuffers_.push(std::make_shared<SurfaceBufferNode>(surfaceBuffer, fence, orgin_));
441     }
442 #endif
443 }
444 
445 void RosenRenderSurface::PostRenderOnlyTaskToUI()
446 {
447     auto task = [weak = renderContext_]() {
448         auto renderContext = weak.Upgrade();
449         CHECK_NULL_VOID(renderContext);
450         auto host = renderContext->GetHost();
451         CHECK_NULL_VOID(host);
452         host->MarkNeedRenderOnly();
453     };
454     auto container = AceEngine::Get().GetContainer(instanceId_);
455     CHECK_NULL_VOID(container);
456     auto context = container->GetPipelineContext();
457     CHECK_NULL_VOID(context);
458     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
459     if (uiTaskExecutor.IsRunOnCurrentThread()) {
460         task();
461     } else {
462         uiTaskExecutor.PostTask(task, "ArkUIMarkNeedRenderOnly");
463     }
464 }
465 
466 void RosenRenderSurface::ConsumeXComponentBuffer()
467 {
468 #ifdef OHOS_PLATFORM
469     ContainerScope scope(instanceId_);
470     CHECK_NULL_VOID(consumerSurface_);
471 
472     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
473     sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
474     int64_t timestamp = 0;
475     OHOS::Rect damage;
476 
477     SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, acquireFence, timestamp, damage);
478     if (surfaceErr != SURFACE_ERROR_OK || !surfaceBuffer) {
479         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "XComponent cannot acquire buffer error = %{public}d", surfaceErr);
480         return;
481     }
482     if (!isUniRender_.load() && !isShow_.load()) {
483         consumerSurface_->ReleaseBuffer(surfaceBuffer, SyncFence::INVALID_FENCE);
484         return;
485     }
486     MarkDirtyIfNeeded();
487     auto surfaceNode = std::make_shared<SurfaceBufferNode>(surfaceBuffer, acquireFence, orgin_);
488     CHECK_NULL_VOID(surfaceNode);
489     surfaceNode->bufferId_ = surfaceBuffer->GetSeqNum();
490     InsertSurfaceNode(surfaceNode);
491     ACE_SCOPED_TRACE("ConsumeXComponentBuffer[id:%u][sendTimes:%d][size:%u]", surfaceNode->bufferId_,
492         surfaceNode->sendTimes_, static_cast<uint32_t>(buffersToDraw_.size()));
493 #endif
494 }
495 
496 void RosenRenderSurface::ReleaseSurfaceBuffers()
497 {
498 #ifdef OHOS_PLATFORM
499     CHECK_NULL_VOID(producerSurface_);
500     producerSurface_->CleanCache();
501     CHECK_NULL_VOID(consumerSurface_);
502     {
503         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
504         if (buffersToDraw_.empty()) {
505             ReleaseAllButLastBuffer(buffersToRelease_, consumerSurface_);
506         } else {
507             ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
508             ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
509         }
510     }
511     consumerSurface_->CleanCache();
512 #endif
513 }
514 
515 /**
516  * if in uniRender just to markDirty
517  * if not, markDirty only when there is no buffer send to RS/RT before
518  **/
519 void RosenRenderSurface::MarkDirtyIfNeeded()
520 {
521     if (isUniRender_.load() || sendCount_.load() < 1) {
522         PostRenderOnlyTaskToUI();
523     }
524 }
525 
526 #ifdef OHOS_PLATFORM
527 void RosenRenderSurface::InsertSurfaceNode(const std::shared_ptr<SurfaceBufferNode>& surfaceNode)
528 {
529     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
530     if (isUniRender_.load()) {
531         auto lastSurfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
532         if (lastSurfaceNode && lastSurfaceNode->sendTimes_ <= 0) {
533             ACE_SCOPED_TRACE("ReleaseXComponentBuffer[id:%u][sendTimes:%d]", lastSurfaceNode->bufferId_,
534                 lastSurfaceNode->sendTimes_);
535             consumerSurface_->ReleaseBuffer(lastSurfaceNode->buffer_, SyncFence::INVALID_FENCE);
536             buffersToDraw_.pop_back();
537         }
538     }
539     buffersToDraw_.emplace_back(surfaceNode);
540 }
541 #endif
542 
543 void RosenRenderSurface::DrawBufferForXComponent(
544     RSCanvas& canvas, float width, float height, float offsetX, float offsetY)
545 {
546 #ifdef OHOS_PLATFORM
547     auto renderContext = renderContext_.Upgrade();
548     CHECK_NULL_VOID(renderContext);
549     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
550     {
551         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
552         if (isUniRender_.load()) {
553             surfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
554         } else {
555             if (!buffersToDraw_.empty()) {
556                 surfaceNode = buffersToDraw_.front();
557                 buffersToDraw_.pop_front();
558                 buffersToRelease_.emplace_back(surfaceNode);
559             } else if (!buffersToRelease_.empty()) {
560                 surfaceNode = buffersToRelease_.back();
561             }
562         }
563         if (!surfaceNode) {
564             TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "surfaceNode is null");
565             return;
566         }
567         ++surfaceNode->sendTimes_;
568     }
569     if (!isUniRender_.load()) {
570         sendCount_.fetch_add(1);
571     }
572     auto uid = GetUniqueIdNum();
573     if (uid == 0) {
574         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "DrawSurfaceBuffer uid is invalid");
575     }
576     ACE_SCOPED_TRACE("DrawXComponentBuffer[id:%u][sendTimes:%d][uid:%" PRIu64 "]", surfaceNode->bufferId_,
577         surfaceNode->sendTimes_, uid);
578     auto& recordingCanvas = static_cast<RSRecordingCanvas&>(canvas);
579     Rosen::DrawingSurfaceBufferInfo info { surfaceNode->buffer_, offsetX, offsetY, static_cast<int32_t>(width),
580         static_cast<int32_t>(height), getpid(), GetUniqueIdNum(), surfaceNode->acquireFence_ };
581     recordingCanvas.DrawSurfaceBuffer(info);
582 #endif
583 }
584 
585 void RosenRenderSurface::RegisterBufferCallback()
586 {
587 #ifdef OHOS_PLATFORM
588     CHECK_EQUAL_VOID(isTexture_, false);
589     auto uid = GetUniqueIdNum();
590     if (!bufferCallback_) {
591         bufferCallback_ = std::make_shared<XComponentSurfaceBufferCallback>(WeakClaim(this));
592     }
593     if (uid == 0) {
594         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "RegisterBufferCallback uid is invalid");
595     }
596     Rosen::RSInterfaces::GetInstance().RegisterSurfaceBufferCallback(getpid(), uid, bufferCallback_);
597     auto rosenRenderContext = DynamicCast<RosenRenderContext>(renderContext_.Upgrade());
598     CHECK_NULL_VOID(rosenRenderContext);
599     auto rsNode = rosenRenderContext->GetRSNode();
600     CHECK_NULL_VOID(rsNode);
601     rsNode->SetExportTypeChangedCallback([weak = WeakClaim(this)](bool isExportTexture) {
602         auto renderSurface = weak.Upgrade();
603         CHECK_NULL_VOID(renderSurface);
604         renderSurface->SetIsUniRender(!isExportTexture);
605     });
606 #endif
607 }
608 
609 void RosenRenderSurface::ReleaseSurfaceBufferById(uint32_t bufferId)
610 {
611     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
612     auto iter = buffersToDraw_.begin();
613     while (iter != buffersToDraw_.end()) {
614         auto surfaceNode = *iter;
615         if (!surfaceNode) {
616             iter = buffersToDraw_.erase(iter);
617         } else if (surfaceNode->bufferId_ == bufferId) {
618             // at least reserve one buffer
619             auto isLast = (buffersToDraw_.size() == 1);
620             ACE_SCOPED_TRACE(
621                 "ReleaseXComponentBuffer[id:%u][sendTimes:%d][isLast:%d]", bufferId, surfaceNode->sendTimes_, isLast);
622             if (--surfaceNode->sendTimes_ <= 0 && !isLast) {
623                 consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
624                 buffersToDraw_.erase(iter);
625             }
626             return;
627         } else {
628             ++iter;
629         }
630     }
631 }
632 
633 void RosenRenderSurface::SetIsUniRender(bool isUniRender)
634 {
635     if (isUniRender_.load() == isUniRender) {
636         return;
637     }
638     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
639     if (buffersToDraw_.empty()) {
640         auto lastSurfaceNode = buffersToRelease_.empty() ? nullptr : buffersToRelease_.back();
641         if (lastSurfaceNode) {
642             buffersToRelease_.pop_back();
643             buffersToDraw_.emplace_back(lastSurfaceNode);
644         }
645     }
646     ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
647     ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
648     // buffersToDraw_ has 1 buffer at most, so .back() equals .front()
649     auto lastSurfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
650     if (lastSurfaceNode) {
651         lastSurfaceNode->sendTimes_ = 0;
652     }
653     sendCount_.store(-1);
654     isUniRender_.store(isUniRender);
655     PostRenderOnlyTaskToUI();
656 }
657 
658 #ifdef OHOS_PLATFORM
659 void RosenRenderSurface::ReleaseSurfaceBufferForRT(const Rosen::FinishCallbackRet& ret)
660 {
661     auto surfaceBufferIds = ret.surfaceBufferIds;
662     if (surfaceBufferIds.empty()) {
663         return;
664     }
665     auto releaseFences = ret.releaseFences;
666     if (surfaceBufferIds.size() != releaseFences.size()) {
667         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "SurfaceBufferCallback OnFinish size not match");
668     }
669     auto idIter = surfaceBufferIds.begin();
670     auto fenceIter = releaseFences.begin();
671     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
672     for (; idIter != surfaceBufferIds.end() && fenceIter != releaseFences.end(); ++idIter, ++fenceIter) {
673         auto iter = buffersToRelease_.begin();
674         while (iter != buffersToRelease_.end()) {
675             auto surfaceNode = *iter;
676             if (!surfaceNode) {
677                 iter = buffersToRelease_.erase(iter);
678             } else if (surfaceNode->bufferId_ == *idIter) {
679                 sendCount_.fetch_sub(1);
680                 surfaceNode->releaseFence_ = *fenceIter;
681                 auto isLast = buffersToDraw_.empty() ? (buffersToRelease_.size() == 1) : false;
682                 ACE_SCOPED_TRACE("ReleaseXComponentBuffer[id:%u][sendTimes:%d][isLast:%d]", surfaceNode->bufferId_,
683                     surfaceNode->sendTimes_, isLast);
684                 if (--surfaceNode->sendTimes_ <= 0 && !isLast) {
685                     consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
686                     buffersToRelease_.erase(iter);
687                 }
688                 break;
689             } else {
690                 ++iter;
691             }
692         }
693     }
694     if (!buffersToDraw_.empty()) {
695         PostRenderOnlyTaskToUI();
696     }
697 }
698 #endif
699 
700 void RosenRenderSurface::OnWindowStateChange(bool isShow)
701 {
702     if (isUniRender_.load()) {
703         return;
704     }
705     if (isShow_.load() == isShow) {
706         return;
707     }
708     ACE_SCOPED_TRACE("RenderSurface::OnWindowState[isShow:%d]", isShow);
709     isShow_.store(isShow);
710     if (!isShow) {
711         CHECK_NULL_VOID(consumerSurface_);
712         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
713         if (buffersToDraw_.empty()) {
714             ReleaseAllButLastBuffer(buffersToRelease_, consumerSurface_);
715             sendCount_.store(
716                 buffersToRelease_.empty() ? -1 : static_cast<int32_t>(buffersToRelease_.front()->sendTimes_ - 1));
717         } else {
718             ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
719             ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
720             sendCount_.store(-1);
721         }
722     }
723 }
724 
725 void DrawBufferListener::OnBufferAvailable()
726 {
727     auto renderSurface = renderSurface_.Upgrade();
728     CHECK_NULL_VOID(renderSurface);
729     if (renderSurface->GetPatternType() == PATTERN_TYPE_WEB) {
730         renderSurface->ConsumeWebBuffer();
731     } else {
732         renderSurface->ConsumeXComponentBuffer();
733     }
734 }
735 
736 #ifdef OHOS_PLATFORM
737 void XComponentSurfaceBufferCallback::OnFinish(const Rosen::FinishCallbackRet& ret)
738 {
739     ACE_SCOPED_TRACE(
740         "SurfaceBufferCallback::OnFinish[uid:%" PRIu64 "][size:%zu]", ret.uid, ret.surfaceBufferIds.size());
741     auto renderSurface = renderSurface_.Upgrade();
742     CHECK_NULL_VOID(renderSurface);
743     if (ret.uid != renderSurface->GetUniqueIdNum()) {
744         return;
745     }
746     if (ret.isUniRender) {
747         for (const auto& bufferId : ret.surfaceBufferIds) {
748             renderSurface->ReleaseSurfaceBufferById(bufferId);
749         }
750     } else {
751         renderSurface->ReleaseSurfaceBufferForRT(ret);
752     }
753 }
754 #endif
755 
756 void ExtSurfaceCallback::OnSurfaceCreated(const sptr<Surface>& /* surface */)
757 {
758     auto interface = weakInterface_.Upgrade();
759     if (interface) {
760         interface->ProcessSurfaceCreate();
761     }
762 }
763 
764 void ExtSurfaceCallback::OnSurfaceChanged(const sptr<Surface>& /* surface */, int32_t width, int32_t height)
765 {
766     auto interface = weakInterface_.Upgrade();
767     if (interface) {
768         interface->ProcessSurfaceChange(width, height);
769     }
770 }
771 
772 void ExtSurfaceCallback::OnSurfaceDestroyed()
773 {
774     auto interface = weakInterface_.Upgrade();
775     if (interface) {
776         interface->ProcessSurfaceDestroy();
777     }
778 }
779 } // namespace OHOS::Ace::NG
780