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