• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "common/rs_optional_trace.h"
27 #include "pipeline/rs_draw_cmd_list.h"
28 #include "pipeline/rs_node_map.h"
29 #include "transaction/rs_transaction_proxy.h"
30 #include "ui/rs_ui_context.h"
31 #ifdef RS_ENABLE_VK
32 #include "modifier_render_thread/rs_modifiers_draw.h"
33 #include "modifier_render_thread/rs_modifiers_draw_thread.h"
34 #include "media_errors.h"
35 #endif
36 
37 namespace OHOS {
38 namespace Rosen {
Create(bool isRenderServiceNode,bool isTextureExportNode,std::shared_ptr<RSUIContext> rsUIContext)39 RSCanvasNode::SharedPtr RSCanvasNode::Create(
40     bool isRenderServiceNode, bool isTextureExportNode, std::shared_ptr<RSUIContext> rsUIContext)
41 {
42     SharedPtr node(new RSCanvasNode(isRenderServiceNode, isTextureExportNode, rsUIContext));
43     if (rsUIContext != nullptr) {
44         rsUIContext->GetMutableNodeMap().RegisterNode(node);
45     } else {
46         RSNodeMap::MutableInstance().RegisterNode(node);
47     }
48 
49     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeCreate>(node->GetId(), isTextureExportNode);
50     node->AddCommand(command, node->IsRenderServiceNode());
51     node->SetUIContextToken();
52     return node;
53 }
54 
RSCanvasNode(bool isRenderServiceNode,bool isTextureExportNode,std::shared_ptr<RSUIContext> rsUIContext)55 RSCanvasNode::RSCanvasNode(bool isRenderServiceNode, bool isTextureExportNode, std::shared_ptr<RSUIContext> rsUIContext)
56     : RSNode(isRenderServiceNode, isTextureExportNode, rsUIContext) {}
57 
RSCanvasNode(bool isRenderServiceNode,NodeId id,bool isTextureExportNode,std::shared_ptr<RSUIContext> rsUIContext)58 RSCanvasNode::RSCanvasNode(bool isRenderServiceNode, NodeId id, bool isTextureExportNode,
59     std::shared_ptr<RSUIContext> rsUIContext)
60     : RSNode(isRenderServiceNode, id, isTextureExportNode, rsUIContext) {}
61 
~RSCanvasNode()62 RSCanvasNode::~RSCanvasNode()
63 {
64 #ifdef RS_ENABLE_VK
65     if (IsHybridRenderCanvas()) {
66         RSModifiersDraw::RemoveSurfaceByNodeId(GetId(), true);
67     }
68 #endif
69 }
70 
SetHDRPresent(bool hdrPresent)71 void RSCanvasNode::SetHDRPresent(bool hdrPresent)
72 {
73     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeSetHDRPresent>(GetId(), hdrPresent);
74     if (AddCommand(command, true)) {
75         ROSEN_LOGD("RSCanvasNode::SetHDRPresent HDRClient set hdr true");
76     }
77 }
78 
SetColorGamut(uint32_t colorGamut)79 void RSCanvasNode::SetColorGamut(uint32_t colorGamut)
80 {
81     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeSetColorGamut>(GetId(), colorGamut);
82     AddCommand(command, true);
83 }
84 
BeginRecording(int width,int height)85 ExtendRecordingCanvas* RSCanvasNode::BeginRecording(int width, int height)
86 {
87     if (recordingCanvas_) {
88         delete recordingCanvas_;
89         recordingCanvas_ = nullptr;
90         RS_LOGE("RSCanvasNode::BeginRecording last beginRecording without finishRecording");
91     }
92 
93     recordingCanvas_ = new ExtendRecordingCanvas(width, height);
94     recordingCanvas_->SetIsCustomTextType(isCustomTextType_);
95     recordingCanvas_->SetIsCustomTypeface(isCustomTypeface_);
96     if (auto recording = recordingCanvas_->GetDrawCmdList()) {
97         recording->SetIsNeedUnmarshalOnDestruct(!IsRenderServiceNode());
98     }
99     if (!recordingUpdated_) {
100         return recordingCanvas_;
101     }
102     recordingUpdated_ = false;
103     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeClearRecording>(GetId());
104     AddCommand(command, IsRenderServiceNode());
105     return recordingCanvas_;
106 }
107 
IsRecording() const108 bool RSCanvasNode::IsRecording() const
109 {
110     return recordingCanvas_ != nullptr;
111 }
112 
RegisterNodeMap()113 void RSCanvasNode::RegisterNodeMap()
114 {
115     auto rsContext = GetRSUIContext();
116     if (rsContext == nullptr) {
117         return;
118     }
119     auto& nodeMap = rsContext->GetMutableNodeMap();
120     nodeMap.RegisterNode(shared_from_this());
121 }
122 
CreateRenderNodeForTextureExportSwitch()123 void RSCanvasNode::CreateRenderNodeForTextureExportSwitch()
124 {
125     if (IsRenderServiceNode()) {
126         hasCreateRenderNodeInRS_ = true;
127     } else {
128         hasCreateRenderNodeInRT_ = true;
129     }
130     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasNodeCreate>(GetId(), isTextureExportNode_);
131     AddCommand(command, IsRenderServiceNode());
132 }
133 
FinishRecording()134 void RSCanvasNode::FinishRecording()
135 {
136     if (!IsRecording()) {
137         return;
138     }
139     auto recording = recordingCanvas_->GetDrawCmdList();
140     delete recordingCanvas_;
141     recordingCanvas_ = nullptr;
142     if (recording && recording->IsEmpty()) {
143         return;
144     }
145     if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
146         // replace drawOpItem with cached one (generated by CPU)
147         recording->GenerateCache();
148     }
149 
150     auto modifierType = static_cast<uint16_t>(
151         drawContentLast_ ? ModifierNG::RSModifierType::FOREGROUND_STYLE : ModifierNG::RSModifierType::CONTENT_STYLE);
152     std::unique_ptr<RSCommand> command =
153         std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording, modifierType);
154     AddCommand(command, IsRenderServiceNode());
155     recordingUpdated_ = true;
156 }
157 
DrawOnNode(RSModifierType type,DrawFunc func)158 void RSCanvasNode::DrawOnNode(RSModifierType type, DrawFunc func)
159 {
160     auto recordingCanvas = std::make_shared<ExtendRecordingCanvas>(GetPaintWidth(), GetPaintHeight());
161     recordingCanvas->SetIsCustomTextType(isCustomTextType_);
162     recordingCanvas->SetIsCustomTypeface(isCustomTypeface_);
163     func(recordingCanvas);
164 
165     auto recording = recordingCanvas->GetDrawCmdList();
166     if (recording) {
167         recording->SetIsNeedUnmarshalOnDestruct(!IsRenderServiceNode());
168     }
169     if (recording && recording->IsEmpty()) {
170         return;
171     }
172     RSNode::SetDrawNode();
173     if (recording != nullptr && RSSystemProperties::GetDrawTextAsBitmap()) {
174         // replace drawOpItem with cached one (generated by CPU)
175         recording->GenerateCache();
176     }
177     auto modifierType = static_cast<uint16_t>(ModifierTypeConvertor::ToModifierNGType(type));
178     std::unique_ptr<RSCommand> command =
179         std::make_unique<RSCanvasNodeUpdateRecording>(GetId(), recording, modifierType);
180     if (AddCommand(command, IsRenderServiceNode())) {
181         recordingUpdated_ = true;
182     }
183 }
184 
GetPaintWidth() const185 float RSCanvasNode::GetPaintWidth() const
186 {
187     auto frame = GetStagingProperties().GetFrame();
188     return frame.z_ <= 0.f ? GetStagingProperties().GetBounds().z_ : frame.z_;
189 }
190 
GetPaintHeight() const191 float RSCanvasNode::GetPaintHeight() const
192 {
193     auto frame = GetStagingProperties().GetFrame();
194     return frame.w_ <= 0.f ? GetStagingProperties().GetBounds().w_ : frame.w_;
195 }
196 
SetFreeze(bool isFreeze)197 void RSCanvasNode::SetFreeze(bool isFreeze)
198 {
199     if (!IsUniRenderEnabled()) {
200         ROSEN_LOGE("SetFreeze is not supported in separate render");
201         return;
202     }
203     RS_OPTIONAL_TRACE_NAME_FMT("RSCanvasNode::SetFreeze id:%llu", GetId());
204     RSNode::SetDrawNode();
205     std::unique_ptr<RSCommand> command = std::make_unique<RSSetFreeze>(GetId(), isFreeze);
206     AddCommand(command, true);
207 }
208 
OnBoundsSizeChanged() const209 void RSCanvasNode::OnBoundsSizeChanged() const
210 {
211     auto bounds = GetStagingProperties().GetBounds();
212     std::lock_guard<std::mutex> lock(mutex_);
213     if (boundsChangedCallback_) {
214         boundsChangedCallback_(bounds);
215     }
216 }
217 
SetBoundsChangedCallback(BoundsChangedCallback callback)218 void RSCanvasNode::SetBoundsChangedCallback(BoundsChangedCallback callback)
219 {
220   std::lock_guard<std::mutex> lock(mutex_);
221   boundsChangedCallback_ = callback;
222 }
223 
GetBitmap(Drawing::Bitmap & bitmap,std::shared_ptr<Drawing::DrawCmdList> drawCmdList)224 bool RSCanvasNode::GetBitmap(Drawing::Bitmap& bitmap, std::shared_ptr<Drawing::DrawCmdList> drawCmdList)
225 {
226     if (!IsHybridRenderCanvas()) {
227         return false;
228     }
229     bool ret = false;
230 #ifdef RS_ENABLE_VK
231     RSModifiersDrawThread::Instance().PostSyncTask([this, &bitmap, &ret]() {
232         auto pixelMap = RSModifiersDraw::GetPixelMapByNodeId(GetId(), false);
233         if (pixelMap == nullptr) {
234             RS_LOGE("RSCanvasNode::GetBitmap pixelMap is nullptr");
235             return;
236         }
237         Drawing::ImageInfo info(
238             pixelMap->GetWidth(), pixelMap->GetHeight(), Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL);
239         if (!bitmap.InstallPixels(info, pixelMap->GetWritablePixels(), pixelMap->GetRowBytes())) {
240             RS_LOGE("RSCanvasNode::GetBitmap get bitmap fail");
241             return;
242         }
243         ret = true;
244     });
245 #endif
246     return ret;
247 }
248 
GetPixelmap(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Drawing::DrawCmdList> drawCmdList,const Drawing::Rect * rect)249 bool RSCanvasNode::GetPixelmap(std::shared_ptr<Media::PixelMap> pixelMap,
250     std::shared_ptr<Drawing::DrawCmdList> drawCmdList, const Drawing::Rect* rect)
251 {
252     if (!IsHybridRenderCanvas()) {
253         return false;
254     }
255     if (pixelMap == nullptr || rect == nullptr) {
256         RS_LOGE("RSCanvasNode::GetPixelmap pixelMap or rect is nullptr");
257         return false;
258     }
259     bool ret = false;
260 #ifdef RS_ENABLE_VK
261     RSModifiersDrawThread::Instance().PostSyncTask([this, pixelMap, rect, &ret]() {
262         auto srcPixelMap = RSModifiersDraw::GetPixelMapByNodeId(GetId(), false);
263         if (srcPixelMap == nullptr) {
264             RS_LOGE("RSCanvasNode::GetPixelmap get source pixelMap fail");
265             return;
266         }
267         Media::Rect srcRect = { rect->GetLeft(), rect->GetTop(), rect->GetWidth(), rect->GetHeight() };
268         auto ret =
269             srcPixelMap->ReadPixels(Media::RWPixelsOptions { static_cast<uint8_t*>(pixelMap->GetWritablePixels()),
270                 pixelMap->GetByteCount(), 0, pixelMap->GetRowStride(), srcRect, Media::PixelFormat::RGBA_8888 });
271         if (ret != Media::SUCCESS) {
272             RS_LOGE("RSCanvasNode::GetPixelmap get pixelMap fail");
273             return;
274         }
275         ret = true;
276     });
277 #endif
278     return ret;
279 }
280 
ResetSurface(int width,int height)281 bool RSCanvasNode::ResetSurface(int width, int height)
282 {
283     if (!IsHybridRenderCanvas()) {
284         return false;
285     }
286 #ifdef RS_ENABLE_VK
287     return RSModifiersDraw::ResetSurfaceByNodeId(width, height, GetId(), true, true);
288 #endif
289     return false;
290 }
291 
292 // [Attention] Only used in PC window resize scene now
SetLinkedRootNodeId(NodeId rootNodeId)293 void RSCanvasNode::SetLinkedRootNodeId(NodeId rootNodeId)
294 {
295     ROSEN_LOGI("RSCanvasNode::SetLinkedRootNodeId nodeId: %{public}" PRIu64 ", rootNode: %{public}" PRIu64 "",
296          GetId(), rootNodeId);
297     std::unique_ptr<RSCommand> command =
298         std::make_unique<RSCanvasNodeSetLinkedRootNodeId>(GetId(), rootNodeId);
299     AddCommand(command, true);
300     linkedRootNodeId_ = rootNodeId;
301 }
302 
303 // [Attention] Only used in PC window resize scene now
GetLinkedRootNodeId()304 NodeId RSCanvasNode::GetLinkedRootNodeId()
305 {
306     return linkedRootNodeId_;
307 }
308 
Marshalling(Parcel & parcel) const309 bool RSCanvasNode::Marshalling(Parcel& parcel) const
310 {
311     bool success =
312         parcel.WriteUint64(GetId()) && parcel.WriteBool(IsRenderServiceNode()) && parcel.WriteUint64(linkedRootNodeId_);
313     if (!success) {
314         ROSEN_LOGE("RSCanvasNode::Marshalling, read parcel failed");
315     }
316     return success;
317 }
318 
Unmarshalling(Parcel & parcel)319 RSCanvasNode::SharedPtr RSCanvasNode::Unmarshalling(Parcel& parcel)
320 {
321     uint64_t id = UINT64_MAX;
322     NodeId linkedRootNodeId = INVALID_NODEID;
323     bool isRenderServiceNode = false;
324     if (!(parcel.ReadUint64(id) && parcel.ReadBool(isRenderServiceNode) && parcel.ReadUint64(linkedRootNodeId))) {
325         ROSEN_LOGE("RSCanvasNode::Unmarshalling, read param failed");
326         return nullptr;
327     }
328 
329     if (auto prevNode = RSNodeMap::Instance().GetNode(id)) {
330         RS_LOGW("RSCanvasNode::Unmarshalling, the node id is already in the map");
331         // if the node id is already in the map, we should not create a new node
332         return prevNode->ReinterpretCastTo<RSCanvasNode>();
333     }
334 
335     SharedPtr canvasNode(new RSCanvasNode(isRenderServiceNode, id));
336     RSNodeMap::MutableInstance().RegisterNode(canvasNode);
337 
338     // for nodes constructed by unmarshalling, we should not destroy the corresponding render node on destruction
339     canvasNode->skipDestroyCommandInDestructor_ = true;
340     canvasNode->linkedRootNodeId_ = linkedRootNodeId;
341 
342     return canvasNode;
343 }
344 
345 } // namespace Rosen
346 } // namespace OHOS
347