1 /*
2  * Copyright (c) 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 
16 #include "core/common/render_boundary_manager.h"
17 
18 #include "core/pipeline_ng/pipeline_context.h"
19 
20 namespace OHOS::Ace {
PostTaskRenderBoundary(bool isDebugBoundary,const RefPtr<Container> & container)21 void RenderBoundaryManager::PostTaskRenderBoundary(bool isDebugBoundary, const RefPtr<Container>& container)
22 {
23     std::lock_guard<std::mutex> lock(renderLayoutBoundaryTaskMutex_);
24     auto taskExecutor = container->GetTaskExecutor();
25     CHECK_NULL_VOID(taskExecutor);
26     if (!renderLayoutBoundaryTaskQueue_.empty() && !ResetTaskQueue(isDebugBoundary)) {
27         return;
28     }
29 
30     RenderLayoutBoundaryTask renderTask;
31     renderTask.target = isDebugBoundary;
32     renderTask.updateTask.Reset(
33         [containerWeak = WeakPtr<Container>(container), isDebugBoundary, weak = WeakClaim(this)]() {
34             ACE_SCOPED_TRACE("PostTaskRenderBoundary");
35             auto renderBoundaryManager = weak.Upgrade();
36             CHECK_NULL_VOID(renderBoundaryManager);
37             auto container = containerWeak.Upgrade();
38             CHECK_NULL_VOID(container);
39             auto pipelineContext = container->GetPipelineContext();
40             auto ngPipeline = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
41             CHECK_NULL_VOID(ngPipeline);
42             auto rootNode = ngPipeline->GetRootElement();
43             CHECK_NULL_VOID(rootNode);
44             rootNode->PaintDebugBoundaryTreeAll(isDebugBoundary);
45             ngPipeline->RequestFrame();
46             renderBoundaryManager->RemoveCurrentRenderBoundaryTask();
47         });
48     renderLayoutBoundaryTaskQueue_.push_back(renderTask);
49     taskExecutor->PostTask(
50         renderLayoutBoundaryTaskQueue_.back().updateTask, TaskExecutor::TaskType::UI, "ArkUIRenderLayoutBoundary");
51 }
52 
ResetTaskQueue(bool isDebugBoundary)53 bool RenderBoundaryManager::ResetTaskQueue(bool isDebugBoundary)
54 {
55     if (renderLayoutBoundaryTaskQueue_.front().target == isDebugBoundary) {
56         while (renderLayoutBoundaryTaskQueue_.size() > 1) {
57             if (!renderLayoutBoundaryTaskQueue_.back().updateTask.Cancel()) {
58                 break;
59             }
60             if (!renderLayoutBoundaryTaskQueue_.empty()) {
61                 renderLayoutBoundaryTaskQueue_.pop_back();
62             }
63         }
64         if (renderLayoutBoundaryTaskQueue_.size() == 1) {
65             return false;
66         }
67     } else if (renderLayoutBoundaryTaskQueue_.front().updateTask.Cancel()) {
68         if (!renderLayoutBoundaryTaskQueue_.empty()) {
69             renderLayoutBoundaryTaskQueue_.pop_front();
70         }
71     }
72     return true;
73 }
74 
RemoveCurrentRenderBoundaryTask()75 void RenderBoundaryManager::RemoveCurrentRenderBoundaryTask()
76 {
77     std::lock_guard<std::mutex> lock(renderLayoutBoundaryTaskMutex_);
78     if (!renderLayoutBoundaryTaskQueue_.empty()) {
79         renderLayoutBoundaryTaskQueue_.pop_front();
80     }
81 }
82 } // namespace OHOS::Ace
83 
84