1 /*
2  * Copyright (c) 2021-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 "ui/rs_canvas_node.h"
17 
18 #include <algorithm>
19 #include <string>
20 
21 #include "common/rs_obj_abs_geometry.h"
22 #include "command/rs_canvas_node_command.h"
23 #include "command/rs_node_command.h"
24 #include "platform/common/rs_log.h"
25 #include "common/rs_obj_geometry.h"
26 #include "pipeline/rs_draw_cmd_list.h"
27 #include "pipeline/rs_node_map.h"
28 #include "transaction/rs_transaction_proxy.h"
29 
30 namespace OHOS {
31 namespace Rosen {
Create(bool isRenderServiceNode,bool isTextureExportNode)32 RSCanvasNode::SharedPtr RSCanvasNode::Create(bool isRenderServiceNode, bool isTextureExportNode)
33 {
34     SharedPtr node(new RSCanvasNode(isRenderServiceNode, isTextureExportNode));
35     RSNodeMap::MutableInstance().RegisterNode(node);
36 
37     auto transactionProxy = RSTransactionProxy::GetInstance();
38     if (transactionProxy == nullptr) {
39         return node;
40     }
41     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeCreate>(node->GetId(), isTextureExportNode);
42     transactionProxy->AddCommand(command, node->IsRenderServiceNode());
43     return node;
44 }
45 
RSCanvasNode(bool isRenderServiceNode,bool isTextureExportNode)46 RSCanvasNode::RSCanvasNode(bool isRenderServiceNode, bool isTextureExportNode)
47     : RSNode(isRenderServiceNode, isTextureExportNode) {}
48 
~RSCanvasNode()49 RSCanvasNode::~RSCanvasNode()
50 {}
51 
SetHDRPresent(bool hdrPresent)52 void RSCanvasNode::SetHDRPresent(bool hdrPresent)
53 {
54     std::unique_ptr<RSCommand> command =
55         std::make_unique<RSCanvasNodeSetHDRPresent>(GetId(), hdrPresent);
56     auto transactionProxy = RSTransactionProxy::GetInstance();
57     if (transactionProxy != nullptr) {
58         ROSEN_LOGD("RSCanvasNode::SetHDRPresent HDRClient set hdr true");
59         transactionProxy->AddCommand(command, true);
60     }
61 }
62 
BeginRecording(int width,int height)63 ExtendRecordingCanvas* RSCanvasNode::BeginRecording(int width, int height)
64 {
65     recordingCanvas_ = new ExtendRecordingCanvas(width, height);
66     recordingCanvas_->SetIsCustomTextType(isCustomTextType_);
67     recordingCanvas_->SetIsCustomTypeface(isCustomTypeface_);
68     if (auto recording = recordingCanvas_->GetDrawCmdList()) {
69         recording->SetIsNeedUnmarshalOnDestruct(!IsRenderServiceNode());
70     }
71     auto transactionProxy = RSTransactionProxy::GetInstance();
72     if (transactionProxy == nullptr) {
73         return recordingCanvas_;
74     }
75     if (!recordingUpdated_) {
76         return recordingCanvas_;
77     }
78     recordingUpdated_ = false;
79     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeClearRecording>(GetId());
80     transactionProxy->AddCommand(command, IsRenderServiceNode());
81     return recordingCanvas_;
82 }
83 
IsRecording() const84 bool RSCanvasNode::IsRecording() const
85 {
86     return recordingCanvas_ != nullptr;
87 }
88 
CreateRenderNodeForTextureExportSwitch()89 void RSCanvasNode::CreateRenderNodeForTextureExportSwitch()
90 {
91     auto transactionProxy = RSTransactionProxy::GetInstance();
92     if (transactionProxy == nullptr) {
93         return;
94     }
95     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeCreate>(GetId(), isTextureExportNode_);
96     if (IsRenderServiceNode()) {
97         hasCreateRenderNodeInRS_ = true;
98     } else {
99         hasCreateRenderNodeInRT_ = true;
100     }
101     transactionProxy->AddCommand(command, IsRenderServiceNode());
102 }
103 
FinishRecording()104 void RSCanvasNode::FinishRecording()
105 {
106     if (!IsRecording()) {
107         return;
108     }
109     auto recording = recordingCanvas_->GetDrawCmdList();
110     delete recordingCanvas_;
111     recordingCanvas_ = nullptr;
112     if (recording && recording->IsEmpty()) {
113         return;
114     }
115     if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
116         // replace drawOpItem with cached one (generated by CPU)
117         recording->GenerateCache();
118     }
119     auto transactionProxy = RSTransactionProxy::GetInstance();
120     if (transactionProxy == nullptr) {
121         return;
122     }
123     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording,
124         drawContentLast_ ? static_cast<uint16_t>(RSModifierType::FOREGROUND_STYLE)
125                          : static_cast<uint16_t>(RSModifierType::CONTENT_STYLE));
126     transactionProxy->AddCommand(command, IsRenderServiceNode());
127     recordingUpdated_ = true;
128 }
129 
DrawOnNode(RSModifierType type,DrawFunc func)130 void RSCanvasNode::DrawOnNode(RSModifierType type, DrawFunc func)
131 {
132     auto recordingCanvas = std::make_shared<ExtendRecordingCanvas>(GetPaintWidth(), GetPaintHeight());
133     recordingCanvas->SetIsCustomTextType(isCustomTextType_);
134     recordingCanvas->SetIsCustomTypeface(isCustomTypeface_);
135     func(recordingCanvas);
136     auto transactionProxy = RSTransactionProxy::GetInstance();
137     if (transactionProxy == nullptr) {
138         return;
139     }
140     auto recording = recordingCanvas->GetDrawCmdList();
141     if (recording) {
142         recording->SetIsNeedUnmarshalOnDestruct(!IsRenderServiceNode());
143     }
144     if (recording && recording->IsEmpty()) {
145         return;
146     }
147     if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
148         // replace drawOpItem with cached one (generated by CPU)
149         recording->GenerateCache();
150     }
151     std::unique_ptr<RSCommand> command =
152         std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording, static_cast<uint16_t>(type));
153     transactionProxy->AddCommand(command, IsRenderServiceNode());
154     recordingUpdated_ = true;
155 }
156 
GetPaintWidth() const157 float RSCanvasNode::GetPaintWidth() const
158 {
159     auto frame = GetStagingProperties().GetFrame();
160     return frame.z_ <= 0.f ? GetStagingProperties().GetBounds().z_ : frame.z_;
161 }
162 
GetPaintHeight() const163 float RSCanvasNode::GetPaintHeight() const
164 {
165     auto frame = GetStagingProperties().GetFrame();
166     return frame.w_ <= 0.f ? GetStagingProperties().GetBounds().w_ : frame.w_;
167 }
168 
SetFreeze(bool isFreeze)169 void RSCanvasNode::SetFreeze(bool isFreeze)
170 {
171     if (!IsUniRenderEnabled()) {
172         ROSEN_LOGE("SetFreeze is not supported in separate render");
173         return;
174     }
175     std::unique_ptr<RSCommand> command = std::make_unique<RSSetFreeze>(GetId(), isFreeze);
176     auto transactionProxy = RSTransactionProxy::GetInstance();
177     if (transactionProxy != nullptr) {
178         transactionProxy->AddCommand(command, true);
179     }
180 }
181 
OnBoundsSizeChanged() const182 void RSCanvasNode::OnBoundsSizeChanged() const
183 {
184     auto bounds = GetStagingProperties().GetBounds();
185     std::lock_guard<std::mutex> lock(mutex_);
186     if (boundsChangedCallback_) {
187         boundsChangedCallback_(bounds);
188     }
189 }
190 
SetBoundsChangedCallback(BoundsChangedCallback callback)191 void RSCanvasNode::SetBoundsChangedCallback(BoundsChangedCallback callback)
192 {
193     std::lock_guard<std::mutex> lock(mutex_);
194     boundsChangedCallback_ = callback;
195 }
196 
197 } // namespace Rosen
198 } // namespace OHOS
199