1 /*
2  * Copyright (c) 2023 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/components_ng/pattern/node_container/node_container_pattern.h"
17 
18 #include "base/utils/utils.h"
19 #include "core/components_v2/inspector/inspector_constants.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
CheckBeforeAddNode(const RefPtr<UINode> & hostNode,const RefPtr<UINode> & newNode)24 bool CheckBeforeAddNode(const RefPtr<UINode>& hostNode, const RefPtr<UINode>& newNode)
25 {
26     CHECK_NULL_RETURN(hostNode, false);
27     CHECK_NULL_RETURN(newNode, true);
28     if (!(newNode->IsArkTsFrameNode()) && !newNode->GetIsRootBuilderNode()) {
29         TAG_LOGW(AceLogTag::ACE_NODE_CONTAINER, "Cannot return node created by declarative UI function");
30         return false;
31     }
32     auto parent = newNode->GetParent();
33     if (parent && parent != hostNode) {
34         TAG_LOGF(AceLogTag::ACE_NODE_CONTAINER,
35             "Add [id:%{public}d][tag:%{public}s] to [id:%{public}d][tag:%{public}s] with previous parent "
36             "[id:%{public}d][tag:%{public}s]",
37             newNode->GetId(), newNode->GetTag().c_str(), hostNode->GetId(), hostNode->GetTag().c_str(), parent->GetId(),
38             parent->GetTag().c_str());
39     }
40     return true;
41 }
42 } // namespace
43 
RemakeNode()44 void NodeContainerPattern::RemakeNode()
45 {
46     auto host = GetHost();
47     CHECK_NULL_VOID(host);
48     auto newNode = FireMakeFunction();
49     auto oldChild = host->GetChildAtIndex(0);
50     if ((!oldChild && !newNode) || (oldChild && oldChild == newNode)) {
51         return;
52     }
53     host->RemoveChildAtIndex(0);
54     if (newNode) {
55         CHECK_NULL_VOID(CheckBeforeAddNode(host, newNode));
56         host->AddChild(newNode, 0);
57         newNode->UpdateGeometryTransition();
58     }
59     OnAddBaseNode();
60     host->MarkNeedFrameFlushDirty(NG::PROPERTY_UPDATE_MEASURE);
61 }
62 
CleanChild()63 void NodeContainerPattern::CleanChild()
64 {
65     auto host = GetHost();
66     CHECK_NULL_VOID(host);
67     host->RemoveChildAtIndex(0);
68     host->MarkNeedFrameFlushDirty(NG::PROPERTY_UPDATE_MEASURE);
69 }
70 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)71 bool NodeContainerPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
72 {
73     if (config.skipMeasure && config.skipLayout) {
74         return false;
75     }
76     auto host = GetHost();
77     CHECK_NULL_RETURN(host, false);
78     auto context = host->GetContext();
79     CHECK_NULL_RETURN(context, false);
80     if (config.frameSizeChange) {
81         auto geometryNode = dirty->GetGeometryNode();
82         auto size = geometryNode->GetFrameSize();
83         context->AddAfterLayoutTask([weak = WeakClaim(this), size]() {
84             auto pattern = weak.Upgrade();
85             CHECK_NULL_VOID(pattern);
86             pattern->FireOnResize(size);
87         });
88     }
89     if (surfaceId_ != 0U && !exportTextureNode_.Invalid()) {
90         context->AddAfterLayoutTask([weak = WeakClaim(this)]() {
91             auto pattern = weak.Upgrade();
92             CHECK_NULL_VOID(pattern);
93             auto ret = pattern->HandleTextureExport(false);
94             if (!ret) {
95                 TAG_LOGW(AceLogTag::ACE_NODE_CONTAINER, "DoTextureExport fail");
96             }
97         });
98     }
99     return false;
100 }
101 
HandleTextureExport(bool isStop)102 bool NodeContainerPattern::HandleTextureExport(bool isStop)
103 {
104     auto exportTextureNode = GetExportTextureNode();
105     CHECK_NULL_RETURN(exportTextureNode, false);
106     auto exportTextureRenderContext = exportTextureNode->GetRenderContext();
107     CHECK_NULL_RETURN(exportTextureRenderContext, false);
108     auto host = GetHost();
109     if (host) {
110         auto renderContext = host->GetRenderContext();
111         CHECK_NULL_RETURN(renderContext, false);
112         renderContext->SetIsNeedRebuildRSTree(isStop);
113     }
114     if (isStop) {
115         return exportTextureRenderContext->StopTextureExport();
116     }
117     return exportTextureRenderContext->DoTextureExport(surfaceId_);
118 }
119 
OnDetachFromFrameNode(FrameNode *)120 void NodeContainerPattern::OnDetachFromFrameNode(FrameNode* /* frameNode */)
121 {
122     HandleTextureExport(true);
123 }
124 
GetExportTextureNode() const125 RefPtr<FrameNode> NodeContainerPattern::GetExportTextureNode() const
126 {
127     auto exportTextureNode = exportTextureNode_.Upgrade();
128     CHECK_NULL_RETURN(exportTextureNode, nullptr);
129     auto exportTextureFrameNode = DynamicCast<FrameNode>(exportTextureNode);
130     while (exportTextureNode && !exportTextureFrameNode) {
131         exportTextureNode = exportTextureNode->GetFirstChild();
132         exportTextureFrameNode = DynamicCast<FrameNode>(exportTextureNode);
133     }
134     return exportTextureFrameNode;
135 }
136 
ResetExportTextureInfo()137 void NodeContainerPattern::ResetExportTextureInfo()
138 {
139     surfaceId_ = 0U;
140     exportTextureNode_.Reset();
141 }
142 
SetExportTextureInfoIfNeeded()143 void NodeContainerPattern::SetExportTextureInfoIfNeeded()
144 {
145     ResetExportTextureInfo();
146     auto host = GetHost();
147     CHECK_NULL_VOID(host);
148     auto viewNode = host->GetChildAtIndex(0);
149     CHECK_NULL_VOID(viewNode);
150     if (!viewNode->IsNeedExportTexture()) {
151         return;
152     }
153     auto parent = host->GetAncestorNodeOfFrame();
154     if (parent) {
155         auto nodeContainer = parent->GetNodeContainer();
156         if (nodeContainer) {
157             auto parentViewNode = nodeContainer->GetChildAtIndex(0);
158             CHECK_NULL_VOID(parentViewNode);
159             auto parnetExportTextureInfo = parentViewNode->GetExportTextureInfo();
160             if (parnetExportTextureInfo &&
161                 parnetExportTextureInfo->GetCurrentRenderType() == NodeRenderType::RENDER_TYPE_TEXTURE) {
162                 return;
163             }
164         }
165     }
166     auto exportTextureInfo = viewNode->GetExportTextureInfo();
167     exportTextureNode_ = viewNode;
168     surfaceId_ = StringUtils::StringToLongUint(exportTextureInfo->GetSurfaceId());
169 }
170 
OnAddBaseNode()171 void NodeContainerPattern::OnAddBaseNode()
172 {
173     HandleTextureExport(true);
174     SetExportTextureInfoIfNeeded();
175 }
176 
OnMountToParentDone()177 void NodeContainerPattern::OnMountToParentDone()
178 {
179     SetExportTextureInfoIfNeeded();
180 }
181 } // namespace OHOS::Ace::NG
182