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