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