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