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