1 /*
2 * Copyright (c) 2021-2022 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 <iostream>
17 #include <surface.h>
18
19 #include "command/rs_base_node_command.h"
20 #include "command/rs_display_node_command.h"
21 #include "command/rs_surface_node_command.h"
22 #include "common/rs_common_def.h"
23
24 #include "pipeline/rs_render_result.h"
25 #include "platform/common/rs_log.h"
26 #include "ui/rs_node.h"
27 #include "ui/rs_surface_extractor.h"
28 #include "ui/rs_ui_director.h"
29 #include "transaction/rs_interfaces.h"
30 #include "ui/rs_display_node.h"
31 #include "ui/rs_surface_node.h"
32 #include "pixel_map.h"
33
34 using namespace OHOS;
35 using namespace OHOS::Rosen;
36 using namespace std;
37
38 std::unique_ptr<RSSurfaceFrame> framePtr;
39
DrawSurface(Drawing::Rect surfaceGeometry,uint32_t color,Drawing::Rect shapeGeometry,std::shared_ptr<RSSurfaceNode> surfaceNode)40 void DrawSurface(Drawing::Rect surfaceGeometry,
41 uint32_t color, Drawing::Rect shapeGeometry, std::shared_ptr<RSSurfaceNode> surfaceNode)
42 {
43 auto x = surfaceGeometry.GetLeft();
44 auto y = surfaceGeometry.GetTop();
45 auto width = surfaceGeometry.GetWidth();
46 auto height = surfaceGeometry.GetHeight();
47 surfaceNode->SetBounds(x, y, width, height);
48 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
49 if (rsSurface == nullptr) {
50 return;
51 }
52 auto frame = rsSurface->RequestFrame(width, height);
53 framePtr = std::move(frame);
54 auto canvas = framePtr->GetCanvas();
55
56 Drawing::Brush brush;
57 brush.SetAntiAlias(true);
58 brush.SetColor(color);
59
60 canvas->AttachBrush(brush);
61 canvas->DrawRect(shapeGeometry);
62 canvas->DetachBrush();
63 framePtr->SetDamageRegion(0, 0, width, height);
64 auto framePtr1 = std::move(framePtr);
65 rsSurface->FlushFrame(framePtr1);
66 }
67
DrawSurfaceToCapture(std::shared_ptr<RSSurfaceNode> surfaceNode)68 void DrawSurfaceToCapture(std::shared_ptr<RSSurfaceNode> surfaceNode)
69 {
70 Drawing::Rect surfaceGeometry = Drawing::Rect(50, 50, 178, 178);
71 Drawing::Rect shapeGeometry = Drawing::Rect(10, 20, 50, 68);
72 auto x = surfaceGeometry.GetLeft();
73 auto y = surfaceGeometry.GetTop();
74 auto width = surfaceGeometry.GetWidth();
75 auto height = surfaceGeometry.GetHeight();
76 surfaceNode->SetBounds(x, y, width, height);
77 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
78 if (rsSurface == nullptr) {
79 ROSEN_LOGE("***SurfaceCaptureTest*** DrawSurfaceToCapture: rsSurface == nullptr");
80 return;
81 }
82 auto frame = rsSurface->RequestFrame(width, height);
83 framePtr = std::move(frame);
84
85 auto canvas = framePtr->GetCanvas();
86 if (canvas == nullptr) {
87 ROSEN_LOGE("***SurfaceCaptureTest*** DrawSurfaceToCapture: canvas == nullptr");
88 return;
89 }
90 Drawing::Brush brush;
91 brush.SetAntiAlias(true);
92 brush.SetColor(0xffff0000);
93 canvas->AttachBrush(brush);
94 canvas->drawRect(shapeGeometry);
95 canvas->DetachBrush();
96
97 Drawing::Path path;
98 path.CubicTo(10, 10, 25, 80, 60, 80);
99 Drawing::Brush pathBrush;
100 pathBrush.SetAntiAlias(true);
101 pathBrush.SetColor(0xffFFD700);
102 canvas->AttachBrush(pathBrush);
103 canvas->drawPath(path);
104 canvas->DetachBrush();
105 framePtr->SetDamageRegion(0, 0, width, height);
106 auto framePtr1 = std::move(framePtr);
107 rsSurface->FlushFrame(framePtr1);
108 }
109
DrawPixelmap(std::shared_ptr<RSSurfaceNode> surfaceNode,std::shared_ptr<Media::PixelMap> pixelmap)110 void DrawPixelmap(std::shared_ptr<RSSurfaceNode> surfaceNode, std::shared_ptr<Media::PixelMap> pixelmap)
111 {
112 std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
113 if (rsSurface == nullptr) {
114 ROSEN_LOGE("***SurfaceCaptureTest*** : rsSurface == nullptr");
115 return;
116 }
117 if (pixelmap == nullptr) {
118 return;
119 }
120 int width = pixelmap->GetWidth();
121 int height = pixelmap->GetHeight();
122 int sWidth = surfaceNode->GetStagingProperties().GetBoundsWidth();
123 int sHeight = surfaceNode->GetStagingProperties().GetBoundsHeight();
124 ROSEN_LOGD("SurfaceCaptureTest: DrawPxielmap [%{public}u][%{public}u][%{public}u][%{public}u]",
125 width, height, sWidth, sHeight);
126 auto frame = rsSurface->RequestFrame(sWidth, sHeight);
127 if (frame == nullptr) {
128 ROSEN_LOGE("***SurfaceCaptureTest*** : frame == nullptr");
129 return;
130 }
131 framePtr = std::move(frame);
132 auto canvas = framePtr->GetCanvas();
133 if (canvas == nullptr) {
134 ROSEN_LOGE("***SurfaceCaptureTest*** : canvas == nullptr");
135 return;
136 }
137 canvas->DrawColor(0xFF87CEEB);
138 Drawing::Bitmap bitmap;
139 bitmap.Build(width, height, Drawing::BitmapFormat{
140 Drawing::ColorType::COLORTYPE_RGBA_8888, Drawing::AlphaType::ALPHATYPE_PREMUL});
141 auto addr = const_cast<uint32_t*>(pixelmap->GetPixel32(0, 0));
142 if (addr == nullptr) {
143 ROSEN_LOGE("***SurfaceCaptureTest*** : addr == nullptr");
144 return;
145 }
146 bitmap.SetPixels(addr);
147
148 Drawing::Image image;
149 image.BuildFromBitmap(bitmap);
150 canvas->DrawImageRect(image, Drawing::Rect(0, 0, sWidth, sHeight), nullptr);
151 framePtr->SetDamageRegion(0, 0, sWidth, sHeight);
152 auto framePtr1 = std::move(framePtr);
153 rsSurface->FlushFrame(framePtr1);
154 }
155
156
CreateSurface()157 std::shared_ptr<RSSurfaceNode> CreateSurface()
158 {
159 RSSurfaceNodeConfig config;
160 config.SurfaceNodeName = "ThisIsSurfaceCaptureName";
161 return RSSurfaceNode::Create(config);
162 }
163
164 // Toy DMS.
165 using DisplayId = ScreenId;
166 class MyDMS {
167 public:
MyDMS()168 MyDMS() : rsInterface_(RSInterfaces::GetInstance())
169 {
170 Init();
171 }
172 ~MyDMS() noexcept = default;
173 RSInterfaces& rsInterface_;
174
GetDefaultDisplayId() const175 DisplayId GetDefaultDisplayId() const
176 {
177 std::lock_guard<std::recursive_mutex> lock(mutex_);
178 return defaultDisplayId_;
179 }
180
GetDisplayActiveMode(DisplayId id) const181 std::optional<RSScreenModeInfo> GetDisplayActiveMode(DisplayId id) const
182 {
183 std::lock_guard<std::recursive_mutex> lock(mutex_);
184 if (displays_.count(id) == 0) {
185 cout << "MyDMS: No display " << id << "!" << endl;
186 return {};
187 }
188 return displays_.at(id).activeMode;
189 }
190
OnDisplayConnected(ScreenId id)191 void OnDisplayConnected(ScreenId id)
192 {
193 std::lock_guard<std::recursive_mutex> lock(mutex_);
194 displays_[id] = Display { id, rsInterface_.GetScreenActiveMode(id) };
195 std::cout << "MyDMS: Display " << id << " connected." << endl;
196 }
197
OnDisplayDisConnected(ScreenId id)198 void OnDisplayDisConnected(ScreenId id)
199 {
200 std::lock_guard<std::recursive_mutex> lock(mutex_);
201 if (displays_.count(id) == 0) {
202 cout << "MyDMS: No display " << id << "!" << endl;
203 } else {
204 std::cout << "MyDMS: Display " << id << " disconnected." << endl;
205 displays_.erase(id);
206 if (id == defaultDisplayId_) {
207 defaultDisplayId_ = rsInterface_.GetDefaultScreenId();
208 std::cout << "MyDMS: DefaultDisplayId changed, new DefaultDisplayId is" << defaultDisplayId_ << "."
209 << endl;
210 }
211 }
212 }
213
214 private:
215 struct Display {
216 DisplayId id;
217 RSScreenModeInfo activeMode;
218 };
219 std::unordered_map<DisplayId, Display> displays_;
220 mutable std::recursive_mutex mutex_;
221 DisplayId defaultDisplayId_;
222
Init()223 void Init()
224 {
225 std::lock_guard<std::recursive_mutex> lock(mutex_);
226 (void)rsInterface_.SetScreenChangeCallback([this](ScreenId id, ScreenEvent event) {
227 switch (event) {
228 case ScreenEvent::CONNECTED: {
229 this->OnDisplayConnected(id);
230 break;
231 }
232 case ScreenEvent::DISCONNECTED: {
233 this->OnDisplayDisConnected(id);
234 break;
235 }
236 default:
237 break;
238 }
239 });
240
241 defaultDisplayId_ = rsInterface_.GetDefaultScreenId();
242 displays_[defaultDisplayId_] =
243 Display { defaultDisplayId_, rsInterface_.GetScreenActiveMode(defaultDisplayId_) };
244 }
245 };
246 MyDMS g_dms;
247
main()248 int main()
249 {
250 DisplayId id = g_dms.GetDefaultDisplayId();
251 cout << "RS default screen id is " << id << ".\n";
252 ROSEN_LOGD("***SurfaceCaptureTest*** main: begin");
253
254 auto surfaceLauncher = CreateSurface();
255 auto surfaceNode1 = CreateSurface();
256 auto surfaceNode2 = CreateSurface();
257 auto surfaceNode3 = CreateSurface();
258 DrawSurface(Drawing::Rect(0, 0, 700, 1000), 0xFFF0FFF0, Drawing::Rect(0, 0, 7000, 1000), surfaceLauncher);
259 DrawSurface(Drawing::Rect(100, 300, 228, 428), 0xFF8B008B, Drawing::Rect(20, 20, 120, 120), surfaceNode1);
260 DrawSurface(Drawing::Rect(100, 600, 356, 856), 0xFF00FF40, Drawing::Rect(20, 20, 120, 120), surfaceNode3);
261 DrawSurfaceToCapture(surfaceNode2);
262 RSDisplayNodeConfig config;
263 config.screenId = id;
264 RSDisplayNode::SharedPtr displayNode = RSDisplayNode::Create(config);
265 displayNode->AddChild(surfaceLauncher, -1);
266 displayNode->AddChild(surfaceNode1, -1);
267 displayNode->AddChild(surfaceNode2, -1);
268 displayNode->AddChild(surfaceNode3, -1);
269 RSTransactionProxy::GetInstance()->FlushImplicitTransaction();
270
271 class TestSurfaceCapture : public SurfaceCaptureCallback {
272 public:
273 explicit TestSurfaceCapture(std::shared_ptr<RSSurfaceNode> surfaceNode) : showNode_(surfaceNode) {}
274 ~TestSurfaceCapture() override {}
275 void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
276 {
277 DrawPixelmap(showNode_, pixelmap);
278 }
279 void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
280 std::shared_ptr<Media::PixelMap> pixelMapHDR) override {}
281 private:
282 std::shared_ptr<RSSurfaceNode> showNode_;
283 };
284 sleep(2);
285 std::shared_ptr<SurfaceCaptureCallback> cb = make_shared<TestSurfaceCapture>(surfaceNode1);
286 RSSurfaceCaptureConfig captureConfig;
287 g_dms.rsInterface_.TakeSurfaceCapture(surfaceNode2, cb, captureConfig);
288 sleep(2);
289 std::shared_ptr<SurfaceCaptureCallback> cb2 = make_shared<TestSurfaceCapture>(surfaceNode3);
290 g_dms.rsInterface_.TakeSurfaceCapture(displayNode, cb2, captureConfig);
291 ROSEN_LOGD("***SurfaceCaptureTest*** main: end");
292 return 0;
293 }