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 "ui/rs_canvas_drawing_node.h"
17 
18 #include "command/rs_canvas_drawing_node_command.h"
19 #include "common/rs_obj_geometry.h"
20 #include "pipeline/rs_canvas_drawing_render_node.h"
21 #include "pipeline/rs_node_map.h"
22 #include "pipeline/rs_render_thread.h"
23 #include "platform/common/rs_log.h"
24 #include "transaction/rs_render_service_client.h"
25 #include "transaction/rs_transaction_proxy.h"
26 
27 namespace OHOS {
28 namespace Rosen {
29 namespace {
30     constexpr int EDGE_WIDTH_LIMIT = 1000;
31 }
RSCanvasDrawingNode(bool isRenderServiceNode,bool isTextureExportNode)32 RSCanvasDrawingNode::RSCanvasDrawingNode(bool isRenderServiceNode, bool isTextureExportNode)
33     : RSCanvasNode(isRenderServiceNode, isTextureExportNode) {}
34 
~RSCanvasDrawingNode()35 RSCanvasDrawingNode::~RSCanvasDrawingNode() {}
36 
Create(bool isRenderServiceNode,bool isTextureExportNode)37 RSCanvasDrawingNode::SharedPtr RSCanvasDrawingNode::Create(bool isRenderServiceNode, bool isTextureExportNode)
38 {
39     SharedPtr node(new RSCanvasDrawingNode(isRenderServiceNode, isTextureExportNode));
40     RSNodeMap::MutableInstance().RegisterNode(node);
41 
42     auto transactionProxy = RSTransactionProxy::GetInstance();
43     if (!transactionProxy) {
44         return node;
45     }
46 
47     std::unique_ptr<RSCommand> command =
48         std::make_unique<RSCanvasDrawingNodeCreate>(node->GetId(), isTextureExportNode);
49     transactionProxy->AddCommand(command, node->IsRenderServiceNode());
50     return node;
51 }
52 
ResetSurface(int width,int height)53 bool RSCanvasDrawingNode::ResetSurface(int width, int height)
54 {
55     auto transactionProxy = RSTransactionProxy::GetInstance();
56     if (!transactionProxy) {
57         return false;
58     }
59     if (width > EDGE_WIDTH_LIMIT) {
60         ROSEN_LOGI("RSCanvasDrawingNode::ResetSurface id:%{public}" PRIu64 " width:%{public}d height:%{public}d",
61             GetId(), width, height);
62     }
63     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasDrawingNodeResetSurface>(GetId(), width, height);
64     transactionProxy->AddCommand(command, IsRenderServiceNode());
65     return true;
66 }
67 
CreateRenderNodeForTextureExportSwitch()68 void RSCanvasDrawingNode::CreateRenderNodeForTextureExportSwitch()
69 {
70     auto transactionProxy = RSTransactionProxy::GetInstance();
71     if (transactionProxy == nullptr) {
72         return;
73     }
74     std::unique_ptr<RSCommand> command = std::make_unique<RSCanvasDrawingNodeCreate>(GetId(), isTextureExportNode_);
75     if (IsRenderServiceNode()) {
76         hasCreateRenderNodeInRS_ = true;
77     } else {
78         hasCreateRenderNodeInRT_ = true;
79     }
80     transactionProxy->AddCommand(command, IsRenderServiceNode());
81 }
82 
GetBitmap(Drawing::Bitmap & bitmap,std::shared_ptr<Drawing::DrawCmdList> drawCmdList,const Drawing::Rect * rect)83 bool RSCanvasDrawingNode::GetBitmap(Drawing::Bitmap& bitmap,
84     std::shared_ptr<Drawing::DrawCmdList> drawCmdList, const Drawing::Rect* rect)
85 {
86     if (IsUniRenderEnabled()) {
87         auto renderServiceClient =
88             std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
89         if (renderServiceClient == nullptr) {
90             ROSEN_LOGE("RSCanvasDrawingNode::GetBitmap renderServiceClient is nullptr!");
91             return false;
92         }
93         bool ret = renderServiceClient->GetBitmap(GetId(), bitmap);
94         if (!ret) {
95             ROSEN_LOGE("RSCanvasDrawingNode::GetBitmap GetBitmap failed");
96             return ret;
97         }
98     } else {
99         auto node =
100             RSRenderThread::Instance().GetContext().GetNodeMap().GetRenderNode<RSCanvasDrawingRenderNode>(GetId());
101         if (node == nullptr) {
102             RS_LOGE("RSCanvasDrawingNode::GetBitmap cannot find NodeId: [%{public}" PRIu64 "]", GetId());
103             return false;
104         }
105         if (node->GetType() != RSRenderNodeType::CANVAS_DRAWING_NODE) {
106             RS_LOGE("RSCanvasDrawingNode::GetBitmap RenderNodeType != RSRenderNodeType::CANVAS_DRAWING_NODE");
107             return false;
108         }
109         auto getBitmapTask = [&node, &bitmap]() { bitmap = node->GetBitmap(); };
110         RSRenderThread::Instance().PostSyncTask(getBitmapTask);
111         if (bitmap.IsValid()) {
112             return false;
113         }
114     }
115     if (drawCmdList == nullptr) {
116         RS_LOGD("RSCanvasDrawingNode::GetBitmap drawCmdList == nullptr");
117     } else {
118         Drawing::Canvas canvas;
119         canvas.Bind(bitmap);
120         drawCmdList->Playback(canvas, rect);
121     }
122     return true;
123 }
124 
GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap,std::shared_ptr<Drawing::DrawCmdList> drawCmdList,const Drawing::Rect * rect)125 bool RSCanvasDrawingNode::GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap,
126     std::shared_ptr<Drawing::DrawCmdList> drawCmdList, const Drawing::Rect* rect)
127 {
128     if (!pixelmap) {
129         RS_LOGE("RSCanvasDrawingNode::GetPixelmap: pixelmap is nullptr");
130         return false;
131     }
132     if (IsUniRenderEnabled()) {
133         auto renderServiceClient =
134             std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
135         if (renderServiceClient == nullptr) {
136             ROSEN_LOGE("RSCanvasDrawingNode::GetPixelmap: renderServiceClient is nullptr!");
137             return false;
138         }
139         bool ret = renderServiceClient->GetPixelmap(GetId(), pixelmap, rect, drawCmdList);
140         if (!ret || !pixelmap) {
141             ROSEN_LOGD("RSCanvasDrawingNode::GetPixelmap: GetPixelmap failed");
142             return false;
143         }
144     } else {
145         auto node =
146             RSRenderThread::Instance().GetContext().GetNodeMap().GetRenderNode<RSCanvasDrawingRenderNode>(GetId());
147         if (node == nullptr) {
148             RS_LOGE("RSCanvasDrawingNode::GetPixelmap: cannot find NodeId: [%{public}" PRIu64 "]", GetId());
149             return false;
150         }
151         if (node->GetType() != RSRenderNodeType::CANVAS_DRAWING_NODE) {
152             RS_LOGE("RSCanvasDrawingNode::GetPixelmap: RenderNodeType != RSRenderNodeType::CANVAS_DRAWING_NODE");
153             return false;
154         }
155         bool ret = false;
156         auto getPixelmapTask = [&node, &pixelmap, rect, &ret, &drawCmdList]() {
157             ret = node->GetPixelmap(pixelmap, rect);
158         };
159         RSRenderThread::Instance().PostSyncTask(getPixelmapTask);
160         if (!ret || !pixelmap) {
161             return false;
162         }
163     }
164     return true;
165 }
166 } // namespace Rosen
167 } // namespace OHOS