• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     const std::string usage = GetBufferUsage();
195     producerSurface_->SetBufferName(usage);
196     auto* surfaceUtils = SurfaceUtils::GetInstance();
197     CHECK_NULL_VOID(surfaceUtils);
198     auto ret = surfaceUtils->Add(producerSurface_->GetUniqueId(), producerSurface_);
199     if (ret != SurfaceError::SURFACE_ERROR_OK) {
200         LOGE("add surface error: %{public}d", ret);
201     }
202 }
203 
UnregisterSurface() const204 void RosenRenderSurface::UnregisterSurface() const
205 {
206     CHECK_NULL_VOID(producerSurface_);
207     auto* surfaceUtils = SurfaceUtils::GetInstance();
208     CHECK_NULL_VOID(surfaceUtils);
209     auto ret = surfaceUtils->Remove(producerSurface_->GetUniqueId());
210     if (ret != SurfaceError::SURFACE_ERROR_OK) {
211         LOGE("remove surface error: %{public}d", ret);
212     }
213 }
214 
UpdateSurfaceConfig()215 void RosenRenderSurface::UpdateSurfaceConfig()
216 {
217     CHECK_NULL_VOID(producerSurface_);
218     producerSurface_->SetQueueSize(queueSize_);
219     producerSurface_->SetUserData("SURFACE_STRIDE_ALIGNMENT", SURFACE_STRIDE_ALIGNMENT);
220     producerSurface_->SetUserData("SURFACE_FORMAT", std::to_string(GRAPHIC_PIXEL_FMT_RGBA_8888));
221 }
222 
GetNativeWindow()223 void* RosenRenderSurface::GetNativeWindow()
224 {
225     return nativeWindow_;
226 }
227 
SetRenderContext(const RefPtr<RenderContext> & renderContext)228 void RosenRenderSurface::SetRenderContext(const RefPtr<RenderContext>& renderContext)
229 {
230     renderContext_ = WeakClaim(RawPtr(renderContext));
231 }
232 
ConfigSurface(uint32_t surfaceWidth,uint32_t surfaceHeight)233 void RosenRenderSurface::ConfigSurface(uint32_t surfaceWidth, uint32_t surfaceHeight)
234 {
235     CHECK_NULL_VOID(producerSurface_);
236     producerSurface_->SetUserData("SURFACE_WIDTH", std::to_string(surfaceWidth));
237     producerSurface_->SetUserData("SURFACE_HEIGHT", std::to_string(surfaceHeight));
238 }
239 
IsSurfaceValid() const240 bool RosenRenderSurface::IsSurfaceValid() const
241 {
242     return producerSurface_ != nullptr;
243 }
244 
CreateNativeWindow()245 void RosenRenderSurface::CreateNativeWindow()
246 {
247     nativeWindow_ = CreateNativeWindowFromSurface(&producerSurface_);
248 }
249 
AdjustNativeWindowSize(uint32_t width,uint32_t height)250 void RosenRenderSurface::AdjustNativeWindowSize(uint32_t width, uint32_t height)
251 {
252     CHECK_NULL_VOID(nativeWindow_);
253     NativeWindowHandleOpt(nativeWindow_, SET_BUFFER_GEOMETRY, width, height);
254 }
255 
UpdateSurfaceSizeInUserData(uint32_t width,uint32_t height)256 void RosenRenderSurface::UpdateSurfaceSizeInUserData(uint32_t width, uint32_t height)
257 {
258     CHECK_NULL_VOID(producerSurface_);
259     producerSurface_->SetUserData(SURFACE_WIDTH, std::to_string(width));
260     producerSurface_->SetUserData(SURFACE_HEIGHT, std::to_string(height));
261 }
262 
GetUniqueId() const263 std::string RosenRenderSurface::GetUniqueId() const
264 {
265     if (!producerSurface_) {
266         return "";
267     }
268     return std::to_string(producerSurface_->GetUniqueId());
269 }
270 
GetUniqueIdNum() const271 uint64_t RosenRenderSurface::GetUniqueIdNum() const
272 {
273     if (!producerSurface_) {
274         return 0;
275     }
276     return producerSurface_->GetUniqueId();
277 }
278 
SetExtSurfaceBounds(int32_t left,int32_t top,int32_t width,int32_t height)279 void RosenRenderSurface::SetExtSurfaceBounds(int32_t left, int32_t top, int32_t width, int32_t height)
280 {
281     if (SystemProperties::GetExtSurfaceEnabled() && surfaceDelegate_) {
282         surfaceDelegate_->SetBounds(left, top, width, height);
283     }
284 }
285 
SetExtSurfaceCallback(const RefPtr<ExtSurfaceCallbackInterface> & extSurfaceCallback)286 void RosenRenderSurface::SetExtSurfaceCallback(const RefPtr<ExtSurfaceCallbackInterface>& extSurfaceCallback)
287 {
288     extSurfaceCallbackInterface_ = extSurfaceCallback;
289 }
290 
SetTransformHint(uint32_t rotation)291 void RosenRenderSurface::SetTransformHint(uint32_t rotation)
292 {
293     auto transform = ConvertRotation(rotation);
294     CHECK_NULL_VOID(producerSurface_);
295     producerSurface_->SetTransformHint(transform);
296 }
297 
DumpInfo()298 void RosenRenderSurface::DumpInfo()
299 {
300     DumpLog::GetInstance().AddDesc(
301         std::string("UserData[surface_width]: ")
302             .append(producerSurface_ ? producerSurface_->GetUserData(SURFACE_WIDTH) : "NoSurface"));
303     DumpLog::GetInstance().AddDesc(
304         std::string("UserData[surface_height]: ")
305             .append(producerSurface_ ? producerSurface_->GetUserData(SURFACE_HEIGHT) : "NoSurface"));
306 }
307 
SetSurfaceDefaultSize(int32_t width,int32_t height)308 void RosenRenderSurface::SetSurfaceDefaultSize(int32_t width, int32_t height)
309 {
310     if (consumerSurface_) {
311         consumerSurface_->SetDefaultWidthAndHeight(width, height);
312     }
313 }
314 
DrawBuffer(int32_t width,int32_t height)315 void RosenRenderSurface::DrawBuffer(int32_t width, int32_t height)
316 {
317 #ifdef OHOS_PLATFORM
318     auto renderContext = renderContext_.Upgrade();
319     CHECK_NULL_VOID(renderContext);
320     auto rosenRenderContext = DynamicCast<RosenRenderContext>(renderContext);
321     CHECK_NULL_VOID(rosenRenderContext);
322     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
323     {
324         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
325 
326         if (availableBuffers_.size() >= 1) {
327             surfaceNode = availableBuffers_.back();
328         }
329     }
330     if (!surfaceNode) {
331         return;
332     }
333     bool res = CompareBufferSize(width, height, surfaceNode);
334     ACE_SCOPED_TRACE("Web DrawBuffer");
335     if (res && isNeedSyncGeometryProperties_) {
336         RectF keyBoardAvoidRect = RectF(keyBoardAvoidRect_.GetX(), keyBoardAvoidRect_.GetY(), width, height);
337         ACE_SCOPED_TRACE("Web DrawBuffer, SyncGeometryProperties: %s", keyBoardAvoidRect.ToString().c_str());
338         rosenRenderContext->SyncGeometryProperties(keyBoardAvoidRect);
339         isNeedSyncGeometryProperties_ = false;
340     }
341     auto rsNode = rosenRenderContext->GetRSNode();
342     CHECK_NULL_VOID(rsNode);
343     rsNode->DrawOnNode(
344 #ifndef USE_ROSEN_DRAWING
345         Rosen::RSModifierType::CONTENT_STYLE, [surfaceNode](const std::shared_ptr<SkCanvas>& canvas) {
346             CHECK_NULL_VOID(canvas);
347             Rosen::RSSurfaceBufferInfo info { surfaceNode->buffer_, surfaceNode->orgin_.GetX(),
348                 surfaceNode->orgin_.GetY(), surfaceNode->buffer_->GetSurfaceBufferWidth(),
349                 surfaceNode->buffer_->GetSurfaceBufferHeight() };
350             auto* recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(canvas.get());
351             CHECK_NULL_VOID(recordingCanvas);
352             recordingCanvas->DrawSurfaceBuffer(info);
353 #else
354         Rosen::RSModifierType::CONTENT_STYLE,
355         [surfaceNode](const std::shared_ptr<RSCanvas>& canvas) {
356             CHECK_NULL_VOID(canvas);
357             Rosen::DrawingSurfaceBufferInfo info { surfaceNode->buffer_, surfaceNode->orgin_.GetX(),
358                 surfaceNode->orgin_.GetY(), surfaceNode->buffer_->GetSurfaceBufferWidth(),
359                 surfaceNode->buffer_->GetSurfaceBufferHeight() };
360             auto* recordingCanvas = static_cast<RSRecordingCanvas*>(canvas.get());
361             CHECK_NULL_VOID(recordingCanvas);
362             recordingCanvas->DrawSurfaceBuffer(info);
363 #endif
364         });
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     CHECK_NULL_RETURN(pipeline, true);
376     ACE_SCOPED_TRACE("Web CompareBufferSize (width %d, height %d, bufferWidth %d, bufferHeight %d)"
377                      " pipeline freeze status = %d",
378         width, height, bufferWidth, bufferHeight, pipeline->IsFreezeFlushMessage());
379     if (bufferWidth > SIZE_LIMIT || bufferHeight > SIZE_LIMIT ||
380         (abs(height - bufferHeight) < PERMITTED_DIFFERENCE && abs(width - bufferWidth) < PERMITTED_DIFFERENCE)) {
381         failTimes_ = 0;
382     } else {
383         failTimes_++;
384         if (failTimes_ <= FAILED_LIMIT) {
385             pipeline->SetIsFreezeFlushMessage(true);
386             ACE_SCOPED_TRACE("Web SetIsFreezeFlushMessage (width %d, height %d, bufferWidth %d, bufferHeight %d)",
387                 width, height, bufferWidth, bufferHeight);
388             return false;
389         }
390     }
391     return true;
392 }
393 #endif
394 
395 void RosenRenderSurface::ConsumeWebBuffer()
396 {
397 #ifdef OHOS_PLATFORM
398     ContainerScope scope(instanceId_);
399     CHECK_NULL_VOID(consumerSurface_);
400 
401     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
402     sptr<SyncFence> fence = SyncFence::INVALID_FENCE;
403     int64_t timestamp = 0;
404     OHOS::Rect damage;
405 
406     SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, fence, timestamp, damage);
407     if (surfaceErr != SURFACE_ERROR_OK) {
408         LOGE("cannot acquire buffer error = %{public}d", surfaceErr);
409         return;
410     }
411     CHECK_NULL_VOID(fence);
412     auto errorCode = fence->Wait(WAIT_FENCE_TIME);
413     LOGD("RosenRenderSurface::ConsumeWebBuffer, wait Fence ,errorCode : %{public}d", errorCode);
414     PostRenderOnlyTaskToUI();
415 
416     int32_t bufferWidth = surfaceBuffer->GetSurfaceBufferWidth();
417     int32_t bufferHeight = surfaceBuffer->GetSurfaceBufferHeight();
418     if (axis_ == Axis::VERTICAL) {
419         if (webOffset_ >= 0 || bufferHeight < ADJUST_WEB_DRAW_LENGTH * 2 || bufferHeight >= DEFAULT_WEB_DRAW_LENGTH) {
420             orgin_.SetY(0);
421         } else {
422             int32_t stepStear = bufferHeight - ADJUST_WEB_DRAW_LENGTH * 2;
423             orgin_.SetY(stepStear * ADJUST_WEB_DRAW_LENGTH);
424         }
425     } else if (axis_ == Axis::HORIZONTAL) {
426         if (webOffset_ >= 0 || bufferWidth < ADJUST_WEB_DRAW_LENGTH * 2 || bufferWidth >= DEFAULT_WEB_DRAW_LENGTH) {
427             orgin_.SetX(0);
428         } else {
429             int32_t stepStear = bufferWidth - ADJUST_WEB_DRAW_LENGTH * 2;
430             orgin_.SetX(stepStear * ADJUST_WEB_DRAW_LENGTH);
431         }
432     }
433     LOGD("ConsumeWebBuffer x : %{public}f, y : %{public}f, width : %{public}d, height : %{public}d", orgin_.GetX(),
434         orgin_.GetY(), bufferWidth, bufferHeight);
435     ACE_SCOPED_TRACE("RosenRenderSurface::ConsumeWebBuffer, bufferWidth %d, bufferHeight %d, orign_x %f, orign_y %f",
436         bufferWidth, bufferHeight, orgin_.GetX(), orgin_.GetY());
437 
438     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
439     {
440         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
441         if (availableBuffers_.size() >= MAX_BUFFER_SIZE) {
442             surfaceNode = availableBuffers_.front();
443             availableBuffers_.pop();
444             consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, SyncFence::INVALID_FENCE);
445         }
446         availableBuffers_.push(std::make_shared<SurfaceBufferNode>(surfaceBuffer, fence, orgin_));
447     }
448 #endif
449 }
450 
451 void RosenRenderSurface::PostRenderOnlyTaskToUI()
452 {
453     auto task = [weak = renderContext_]() {
454         auto renderContext = weak.Upgrade();
455         CHECK_NULL_VOID(renderContext);
456         auto host = renderContext->GetHost();
457         CHECK_NULL_VOID(host);
458         host->MarkNeedRenderOnly();
459     };
460     auto container = AceEngine::Get().GetContainer(instanceId_);
461     CHECK_NULL_VOID(container);
462     auto context = container->GetPipelineContext();
463     CHECK_NULL_VOID(context);
464     auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
465     if (uiTaskExecutor.IsRunOnCurrentThread()) {
466         task();
467     } else {
468         uiTaskExecutor.PostTask(task, "ArkUIMarkNeedRenderOnly");
469     }
470 }
471 
472 void RosenRenderSurface::ConsumeXComponentBuffer()
473 {
474 #ifdef OHOS_PLATFORM
475     ContainerScope scope(instanceId_);
476     CHECK_NULL_VOID(consumerSurface_);
477 
478     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
479     sptr<SyncFence> acquireFence = SyncFence::INVALID_FENCE;
480     int64_t timestamp = 0;
481     OHOS::Rect damage;
482 
483     SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, acquireFence, timestamp, damage);
484     if (surfaceErr != SURFACE_ERROR_OK || !surfaceBuffer) {
485         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "XComponent cannot acquire buffer error = %{public}d", surfaceErr);
486         return;
487     }
488     if (!isUniRender_.load() && !isShow_.load()) {
489         consumerSurface_->ReleaseBuffer(surfaceBuffer, SyncFence::INVALID_FENCE);
490         return;
491     }
492     MarkDirtyIfNeeded();
493     auto surfaceNode = std::make_shared<SurfaceBufferNode>(surfaceBuffer, acquireFence, orgin_);
494     CHECK_NULL_VOID(surfaceNode);
495     surfaceNode->bufferId_ = surfaceBuffer->GetSeqNum();
496     InsertSurfaceNode(surfaceNode);
497     ACE_SCOPED_TRACE("ConsumeXComponentBuffer[id:%u][sendTimes:%d][size:%u]", surfaceNode->bufferId_,
498         surfaceNode->sendTimes_, static_cast<uint32_t>(buffersToDraw_.size()));
499 #endif
500 }
501 
502 void RosenRenderSurface::ReleaseSurfaceBuffers()
503 {
504 #ifdef OHOS_PLATFORM
505     CHECK_NULL_VOID(producerSurface_);
506     producerSurface_->CleanCache();
507     CHECK_NULL_VOID(consumerSurface_);
508     {
509         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
510         if (buffersToDraw_.empty()) {
511             ReleaseAllButLastBuffer(buffersToRelease_, consumerSurface_);
512         } else {
513             ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
514             ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
515         }
516     }
517     consumerSurface_->CleanCache();
518 #endif
519 }
520 
521 /**
522  * if in uniRender just to markDirty
523  * if not, markDirty only when there is no buffer send to RS/RT before
524  **/
525 void RosenRenderSurface::MarkDirtyIfNeeded()
526 {
527     if (isUniRender_.load() || sendCount_.load() < 1) {
528         PostRenderOnlyTaskToUI();
529     }
530 }
531 
532 #ifdef OHOS_PLATFORM
533 void RosenRenderSurface::InsertSurfaceNode(const std::shared_ptr<SurfaceBufferNode>& surfaceNode)
534 {
535     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
536     if (isUniRender_.load()) {
537         auto lastSurfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
538         if (lastSurfaceNode && lastSurfaceNode->sendTimes_ <= 0) {
539             ACE_SCOPED_TRACE("ReleaseXComponentBuffer[id:%u][sendTimes:%d]", lastSurfaceNode->bufferId_,
540                 lastSurfaceNode->sendTimes_);
541             consumerSurface_->ReleaseBuffer(lastSurfaceNode->buffer_, SyncFence::INVALID_FENCE);
542             buffersToDraw_.pop_back();
543         }
544     }
545     buffersToDraw_.emplace_back(surfaceNode);
546 }
547 #endif
548 
549 void RosenRenderSurface::DrawBufferForXComponent(
550     RSCanvas& canvas, float width, float height, float offsetX, float offsetY)
551 {
552 #ifdef OHOS_PLATFORM
553     auto renderContext = renderContext_.Upgrade();
554     CHECK_NULL_VOID(renderContext);
555     std::shared_ptr<SurfaceBufferNode> surfaceNode = nullptr;
556     {
557         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
558         if (isUniRender_.load()) {
559             surfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
560         } else {
561             if (!buffersToDraw_.empty()) {
562                 surfaceNode = buffersToDraw_.front();
563                 buffersToDraw_.pop_front();
564                 buffersToRelease_.emplace_back(surfaceNode);
565             } else if (!buffersToRelease_.empty()) {
566                 surfaceNode = buffersToRelease_.back();
567             }
568         }
569         if (!surfaceNode) {
570             TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "surfaceNode is null");
571             return;
572         }
573         ++surfaceNode->sendTimes_;
574     }
575     if (!isUniRender_.load()) {
576         sendCount_.fetch_add(1);
577     }
578     auto uid = GetUniqueIdNum();
579     if (uid == 0) {
580         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "DrawSurfaceBuffer uid is invalid");
581     }
582     ACE_SCOPED_TRACE("DrawXComponentBuffer[id:%u][sendTimes:%d][uid:%" PRIu64 "]", surfaceNode->bufferId_,
583         surfaceNode->sendTimes_, uid);
584     auto& recordingCanvas = static_cast<RSRecordingCanvas&>(canvas);
585     auto transform = surfaceNode->buffer_ == nullptr
586         ? GraphicTransformType::GRAPHIC_ROTATE_NONE
587         : surfaceNode->buffer_->GetSurfaceBufferTransform();
588     Rosen::DrawingSurfaceBufferInfo info { surfaceNode->buffer_, offsetX, offsetY, static_cast<int32_t>(width),
589         static_cast<int32_t>(height), getpid(), GetUniqueIdNum(), surfaceNode->acquireFence_, transform };
590     recordingCanvas.DrawSurfaceBuffer(info);
591 #endif
592 }
593 
594 void RosenRenderSurface::RegisterBufferCallback()
595 {
596 #ifdef OHOS_PLATFORM
597     CHECK_EQUAL_VOID(isTexture_, false);
598     auto uid = GetUniqueIdNum();
599     if (!bufferCallback_) {
600         bufferCallback_ = std::make_shared<XComponentSurfaceBufferCallback>(WeakClaim(this));
601     }
602     if (uid == 0) {
603         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "RegisterBufferCallback uid is invalid");
604     }
605     Rosen::RSInterfaces::GetInstance().RegisterSurfaceBufferCallback(getpid(), uid, bufferCallback_);
606     auto rosenRenderContext = DynamicCast<RosenRenderContext>(renderContext_.Upgrade());
607     CHECK_NULL_VOID(rosenRenderContext);
608     auto rsNode = rosenRenderContext->GetRSNode();
609     CHECK_NULL_VOID(rsNode);
610     rsNode->SetExportTypeChangedCallback([weak = WeakClaim(this)](bool isExportTexture) {
611         auto renderSurface = weak.Upgrade();
612         CHECK_NULL_VOID(renderSurface);
613         renderSurface->SetIsUniRender(!isExportTexture);
614     });
615 #endif
616 }
617 
618 #ifdef OHOS_PLATFORM
619 void RosenRenderSurface::ReleaseSurfaceBufferById(uint32_t bufferId, sptr<SyncFence> fence)
620 {
621     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
622     auto iter = buffersToDraw_.begin();
623     while (iter != buffersToDraw_.end()) {
624         auto surfaceNode = *iter;
625         if (!surfaceNode) {
626             iter = buffersToDraw_.erase(iter);
627         } else if (surfaceNode->bufferId_ == bufferId) {
628             // at least reserve one buffer
629             auto isLast = (buffersToDraw_.size() == 1);
630             ACE_SCOPED_TRACE(
631                 "ReleaseXComponentBuffer[id:%u][sendTimes:%d][isLast:%d]", bufferId, surfaceNode->sendTimes_, isLast);
632             if (--surfaceNode->sendTimes_ <= 0 && !isLast) {
633                 surfaceNode->releaseFence_ = fence;
634                 consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
635                 buffersToDraw_.erase(iter);
636             }
637             return;
638         } else {
639             ++iter;
640         }
641     }
642 }
643 #endif
644 
645 void RosenRenderSurface::SetIsUniRender(bool isUniRender)
646 {
647     if (isUniRender_.load() == isUniRender) {
648         return;
649     }
650     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
651     if (buffersToDraw_.empty()) {
652         auto lastSurfaceNode = buffersToRelease_.empty() ? nullptr : buffersToRelease_.back();
653         if (lastSurfaceNode) {
654             buffersToRelease_.pop_back();
655             buffersToDraw_.emplace_back(lastSurfaceNode);
656         }
657     }
658     ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
659     ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
660     // buffersToDraw_ has 1 buffer at most, so .back() equals .front()
661     auto lastSurfaceNode = buffersToDraw_.empty() ? nullptr : buffersToDraw_.back();
662     if (lastSurfaceNode) {
663         lastSurfaceNode->sendTimes_ = 0;
664     }
665     sendCount_.store(-1);
666     isUniRender_.store(isUniRender);
667     PostRenderOnlyTaskToUI();
668 }
669 
670 #ifdef OHOS_PLATFORM
671 void RosenRenderSurface::ReleaseSurfaceBufferForRT(const Rosen::FinishCallbackRet& ret)
672 {
673     auto surfaceBufferIds = ret.surfaceBufferIds;
674     if (surfaceBufferIds.empty()) {
675         return;
676     }
677     auto releaseFences = ret.releaseFences;
678     if (surfaceBufferIds.size() != releaseFences.size()) {
679         TAG_LOGW(AceLogTag::ACE_XCOMPONENT, "SurfaceBufferCallback OnFinish size not match");
680     }
681     auto idIter = surfaceBufferIds.begin();
682     auto fenceIter = releaseFences.begin();
683     std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
684     for (; idIter != surfaceBufferIds.end() && fenceIter != releaseFences.end(); ++idIter, ++fenceIter) {
685         auto iter = buffersToRelease_.begin();
686         while (iter != buffersToRelease_.end()) {
687             auto surfaceNode = *iter;
688             if (!surfaceNode) {
689                 iter = buffersToRelease_.erase(iter);
690             } else if (surfaceNode->bufferId_ == *idIter) {
691                 sendCount_.fetch_sub(1);
692                 surfaceNode->releaseFence_ = *fenceIter;
693                 auto isLast = buffersToDraw_.empty() ? (buffersToRelease_.size() == 1) : false;
694                 ACE_SCOPED_TRACE("ReleaseXComponentBuffer[id:%u][sendTimes:%d][isLast:%d]", surfaceNode->bufferId_,
695                     surfaceNode->sendTimes_, isLast);
696                 if (--surfaceNode->sendTimes_ <= 0 && !isLast) {
697                     consumerSurface_->ReleaseBuffer(surfaceNode->buffer_, surfaceNode->releaseFence_);
698                     buffersToRelease_.erase(iter);
699                 }
700                 break;
701             } else {
702                 ++iter;
703             }
704         }
705     }
706     if (!buffersToDraw_.empty()) {
707         PostRenderOnlyTaskToUI();
708     }
709 }
710 #endif
711 
712 void RosenRenderSurface::OnWindowStateChange(bool isShow)
713 {
714     if (isUniRender_.load()) {
715         return;
716     }
717     if (isShow_.load() == isShow) {
718         return;
719     }
720     ACE_SCOPED_TRACE("RenderSurface::OnWindowState[isShow:%d]", isShow);
721     isShow_.store(isShow);
722     if (!isShow) {
723         CHECK_NULL_VOID(consumerSurface_);
724         std::lock_guard<std::mutex> lock(surfaceNodeMutex_);
725         if (buffersToDraw_.empty()) {
726             ReleaseAllButLastBuffer(buffersToRelease_, consumerSurface_);
727             sendCount_.store(
728                 buffersToRelease_.empty() ? -1 : static_cast<int32_t>(buffersToRelease_.front()->sendTimes_ - 1));
729         } else {
730             ReleaseAllBuffers(buffersToRelease_, consumerSurface_);
731             ReleaseAllButLastBuffer(buffersToDraw_, consumerSurface_);
732             sendCount_.store(-1);
733         }
734     }
735 }
736 
737 void DrawBufferListener::OnBufferAvailable()
738 {
739     auto renderSurface = renderSurface_.Upgrade();
740     CHECK_NULL_VOID(renderSurface);
741     if (renderSurface->GetPatternType() == PATTERN_TYPE_WEB) {
742         renderSurface->ConsumeWebBuffer();
743     } else {
744         renderSurface->ConsumeXComponentBuffer();
745     }
746 }
747 
748 #ifdef OHOS_PLATFORM
749 void XComponentSurfaceBufferCallback::OnFinish(const Rosen::FinishCallbackRet& ret)
750 {
751     ACE_SCOPED_TRACE("SurfaceBufferCallback::OnFinish[uid:%" PRIu64 "][size:%zu] isUniRender:[%d]", ret.uid,
752         ret.surfaceBufferIds.size(), ret.isUniRender);
753     auto renderSurface = renderSurface_.Upgrade();
754     CHECK_NULL_VOID(renderSurface);
755     if (ret.uid != renderSurface->GetUniqueIdNum()) {
756         return;
757     }
758     if (ret.isUniRender) {
759         auto surfaceBufferIds = ret.surfaceBufferIds;
760         auto releaseFences = ret.releaseFences;
761         auto idIter = surfaceBufferIds.begin();
762         auto fenceIter = releaseFences.begin();
763         for (; idIter != surfaceBufferIds.end() && fenceIter != releaseFences.end(); ++idIter, ++fenceIter) {
764             renderSurface->ReleaseSurfaceBufferById(*idIter, *fenceIter);
765         }
766     } else {
767         renderSurface->ReleaseSurfaceBufferForRT(ret);
768     }
769 }
770 #endif
771 
772 void ExtSurfaceCallback::OnSurfaceCreated(const sptr<Surface>& /* surface */)
773 {
774     auto interface = weakInterface_.Upgrade();
775     if (interface) {
776         interface->ProcessSurfaceCreate();
777     }
778 }
779 
780 void ExtSurfaceCallback::OnSurfaceChanged(const sptr<Surface>& /* surface */, int32_t width, int32_t height)
781 {
782     auto interface = weakInterface_.Upgrade();
783     if (interface) {
784         interface->ProcessSurfaceChange(width, height);
785     }
786 }
787 
788 void ExtSurfaceCallback::OnSurfaceDestroyed()
789 {
790     auto interface = weakInterface_.Upgrade();
791     if (interface) {
792         interface->ProcessSurfaceDestroy();
793     }
794 }
795 } // namespace OHOS::Ace::NG
796