• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <cstdint>
17 #include <cstdlib>
18 #include <cstring>
19 #include <iostream>
20 #include <sstream>
21 #include "accesstoken_kit.h"
22 #ifdef SUPPORT_ACCESS_TOKEN
23 #include "nativetoken_kit.h"
24 #include "token_setproc.h"
25 #endif
26 #include "display_type.h"
27 #include "draw/canvas.h"
28 #include "draw/color.h"
29 #include "graphic_common.h"
30 #include "image/bitmap.h"
31 #include "include/core/SkColor.h"
32 #include "pixel_map.h"
33 #include "png.h"
34 #include "render_context/render_context.h"
35 #include "surface_type.h"
36 #include "transaction/rs_interfaces.h"
37 #include "transaction/rs_transaction.h"
38 #include "ui/rs_display_node.h"
39 #include "ui/rs_ui_director.h"
40 #include "ui/rs_root_node.h"
41 #include "ui/rs_surface_node.h"
42 #include "ui/rs_surface_extractor.h"
43 #include "window.h"
44 
45 using namespace OHOS;
46 using namespace OHOS::Rosen;
47 using namespace OHOS::Rosen::Drawing;
48 using namespace std;
49 
50 using WriteToPngParam = struct {
51     uint32_t width;
52     uint32_t height;
53     uint32_t stride;
54     uint32_t bitDepth;
55     const uint8_t *data;
56 };
57 
58 constexpr int BITMAP_DEPTH = 8;
59 constexpr int SLEEP_DURATION_LARGE = 4;
60 constexpr int SLEEP_DURATION = 2;
61 constexpr float BLUR_RADIUS_NEGATIVE = -10;
62 constexpr float BLUR_RADIUS_SMALL = 10;
63 constexpr float BLUR_RADIUS_LARGE = 50;
64 
65 shared_ptr<RSNode> rootNode;
66 shared_ptr<RSCanvasNode> canvasNode;
67 shared_ptr<RSCanvasNode> canvasNode2;
68 shared_ptr<RSSurfaceNode> surfaceNode1;
69 shared_ptr<RSSurfaceNode> surfaceNode2;
70 
71 #ifdef RS_ENABLE_GPU
72     RenderContext* rc_ = nullptr;
73 #endif
74 
WriteToPng(const string & fileName,const WriteToPngParam & param)75 bool WriteToPng(const string &fileName, const WriteToPngParam &param)
76 {
77     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
78     if (pngStruct == nullptr) {
79         cout << "png_create_write_struct error, nullptr!" << endl;
80         return false;
81     }
82     png_infop pngInfo = png_create_info_struct(pngStruct);
83     if (pngInfo == nullptr) {
84         cout << "png_create_info_struct error, nullptr!" <<endl;
85         png_destroy_write_struct(&pngStruct, nullptr);
86         return false;
87     }
88     FILE *fp = fopen(fileName.c_str(), "wb");
89     if (fp == nullptr) {
90         cout << "open file error, nullptr!" << endl;
91         png_destroy_write_struct(&pngStruct, &pngInfo);
92         return false;
93     }
94     png_init_io(pngStruct, fp);
95 
96     // set png header
97     png_set_IHDR(pngStruct, pngInfo,
98         param.width, param.height,
99         param.bitDepth,
100         PNG_COLOR_TYPE_RGBA,
101         PNG_INTERLACE_NONE,
102         PNG_COMPRESSION_TYPE_BASE,
103         PNG_FILTER_TYPE_BASE);
104     png_set_packing(pngStruct); // set packing info
105     png_write_info(pngStruct, pngInfo); // write to header
106 
107     for (uint32_t i = 0; i < param.height; i++) {
108         png_write_row(pngStruct, param.data + (i * param.stride));
109     }
110 
111     png_write_end(pngStruct, pngInfo);
112 
113     // free
114     png_destroy_write_struct(&pngStruct, &pngInfo);
115     int ret = fclose(fp);
116     if (ret != 0) {
117         cout << "close fp failed" << endl;
118     }
119     return true;
120 }
121 
RenderContextInit()122 void RenderContextInit()
123 {
124 #ifdef RS_ENABLE_GPU
125     cout << "RS_ENABLE_GPU is true" << endl;
126     cout << "Init RenderContext start" << endl;
127     rc_ = RenderContextFactory::GetInstance().CreateEngine();
128     if (rc_) {
129         cout << "Init RenderContext success" << endl;
130         rc_->InitializeEglContext();
131     } else {
132         cout << "Init RenderContext failed, RenderContext is nullptr" << endl;
133     }
134 #endif
135 }
136 
DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)137 void DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)
138 {
139     int surfaceX = 100;
140     int surfaceY = 50;
141     int surfaceWidth = 300;
142     int surfaceHeight = 600;
143     SkRect surfaceGeometry = SkRect::MakeXYWH(surfaceX, surfaceY, surfaceWidth, surfaceHeight);
144     auto x = surfaceGeometry.x();
145     auto y = surfaceGeometry.y();
146     auto width = surfaceGeometry.width();
147     auto height = surfaceGeometry.height();
148     surfaceNode->SetBounds(x, y, width, height);
149     shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
150     if (rsSurface == nullptr) {
151         cout << "surface is nullptr" << endl;
152         return;
153     }
154 #ifdef RS_ENABLE_GPU
155     if (rc_) {
156         rsSurface->SetRenderContext(rc_);
157     } else {
158         cout << "DrawSurface: RenderContext is nullptr" << endl;
159     }
160 #endif
161     auto framePtr = rsSurface->RequestFrame(width, height);
162     if (!framePtr) {
163         cout << "framePtr is nullptr" << endl;
164         return;
165     }
166     auto canvas = framePtr->GetCanvas();
167     if (!canvas) {
168         cout << "canvas is nullptr" << endl;
169         return;
170     }
171     canvas->Clear(SK_ColorWHITE);
172 
173     Brush brush;
174     brush.SetColor(SK_ColorGREEN);
175     brush.SetAntiAlias(true);
176 
177     Font font = Font();
178     font.SetSize(16); // text size 16
179     std::shared_ptr<TextBlob> scaleInfoTextBlob = TextBlob::MakeFromString("Hello World",
180         font, TextEncoding::UTF8);
181     canvas->AttachBrush(brush);
182     int startpointX = 20;
183     int startpointY = 50;
184     canvas->DrawTextBlob(scaleInfoTextBlob.get(), startpointX, startpointY); // start point is (20, 50)
185     canvas->DetachBrush();
186     framePtr->SetDamageRegion(0, 0, width, height);
187     rsSurface->FlushFrame(framePtr);
188     return;
189 }
190 
WriteToPngWithPixelMap(const string & fileName,Media::PixelMap & pixelMap)191 bool WriteToPngWithPixelMap(const string &fileName, Media::PixelMap &pixelMap)
192 {
193     WriteToPngParam param;
194     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
195     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
196     param.data = pixelMap.GetPixels();
197     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
198     param.bitDepth = BITMAP_DEPTH;
199     return WriteToPng(fileName, param);
200 }
201 
Init(shared_ptr<RSUIDirector> rsUiDirector,int width,int height)202 void Init(shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
203 {
204     cout << "rs local surface capture demo Init Rosen Backend!" << endl;
205 
206     rootNode = RSRootNode::Create();
207     rootNode->SetBounds(0, 0, width, height);
208     rootNode->SetFrame(0, 0, width, height);
209     rootNode->SetBackgroundColor(SK_ColorRED);
210 
211     rsUiDirector->SetRoot(rootNode->GetId());
212     canvasNode = RSCanvasNode::Create();
213     uint32_t firstnodeX = 10;
214     uint32_t firstnodeY = 10;
215     uint32_t firstnodeWidth = 600;
216     uint32_t firstnodeHeight = 1000;
217     canvasNode->SetBounds(firstnodeX, firstnodeY, firstnodeWidth, firstnodeHeight);
218     canvasNode->SetFrame(firstnodeX, firstnodeY, firstnodeWidth, firstnodeHeight);
219     canvasNode->SetBackgroundColor(SK_ColorYELLOW);
220     rootNode->AddChild(canvasNode, -1);
221 
222     uint32_t secondnodeX = 5;
223     uint32_t secondnodeY = 5;
224     uint32_t secondnodeWidth = 400;
225     uint32_t secondnodeHeight = 800;
226     canvasNode2 = RSCanvasNode::Create();
227     canvasNode2->SetBounds(secondnodeX, secondnodeY, secondnodeWidth, secondnodeHeight);
228     canvasNode2->SetFrame(secondnodeX, secondnodeY, secondnodeWidth, secondnodeHeight);
229     canvasNode2->SetBackgroundColor(SK_ColorBLUE);
230     canvasNode->AddChild(canvasNode2, -1);
231 
232     RSSurfaceNodeConfig config;
233     surfaceNode1 = RSSurfaceNode::Create(config, false);
234     RenderContextInit();
235     DrawSurfaceNode(surfaceNode1);
236     canvasNode2->AddChild(surfaceNode1, -1);
237 }
238 
239 class MySurfaceCaptureCallback : public SurfaceCaptureCallback {
240 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap)241     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
242     {
243         static int32_t count = 0;
244         if (pixelmap == nullptr) {
245             cout << "RSUIDirector::LocalCapture failed to get pixelmap, return nullptr!" << endl;
246             return;
247         }
248         cout << "rs local surface demo drawPNG" << endl;
249         string filename = "/data/local/test_" + to_string(count++) + ".jpg";
250         int ret = WriteToPngWithPixelMap(filename, *pixelmap);
251         if (!ret) {
252             cout << "pixelmap write to png failed" << endl;
253         }
254         cout << "pixelmap write to png sucess" << endl;
255     }
256 };
257 
InitNativeTokenInfo()258 void InitNativeTokenInfo()
259 {
260 #ifdef SUPPORT_ACCESS_TOKEN
261     uint64_t tokenId;
262     const char *perms[1];
263     perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
264     NativeTokenInfoParams infoInstance = {
265         .dcapsNum = 0,
266         .permsNum = 1,
267         .aclsNum = 0,
268         .dcaps = NULL,
269         .perms = perms,
270         .acls = NULL,
271         .processName = "rs_uni_render_pixelmap_demo",
272         .aplStr = "system_basic",
273     };
274     tokenId = GetAccessTokenId(&infoInstance);
275     SetSelfTokenID(tokenId);
276     Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
277 #endif
278 }
279 
main()280 int main()
281 {
282 #ifdef SUPPORT_ACCESS_TOKEN
283     InitNativeTokenInfo();
284 
285     cout << "rs local surface capture demo" << endl;
286     sptr<WindowOption> option = new WindowOption();
287     option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
288     option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
289     uint32_t windowWidth = 680;
290     uint32_t windowHeight = 1100;
291     option->SetWindowRect({0, 0, windowWidth, windowHeight});
292     string demoName = "surface_capture_demo";
293     auto window = Window::Create(demoName, option);
294 
295     window->Show();
296     sleep(SLEEP_DURATION);
297     auto rect = window->GetRect();
298     while (rect.width_ == 0 && rect.height_ == 0) {
299         cout << "rs local surface demo create window failed: " << rect.width_ << " " << rect.height_ << endl;
300         window->Hide();
301         window->Destroy();
302         window = Window::Create(demoName, option);
303         window->Show();
304         rect = window->GetRect();
305     }
306     cout << "rs local surface demo create window success: " << rect.width_ << " " << rect.height_ << endl;
307     auto surfaceNode = window->GetSurfaceNode();
308 
309     auto rsUiDirector = RSUIDirector::Create();
310     rsUiDirector->Init();
311     RSTransaction::FlushImplicitTransaction();
312 
313     cout << "rs local surface demo init" << endl;
314     rsUiDirector->SetRSSurfaceNode(surfaceNode);
315     Init(rsUiDirector, rect.width_, rect.height_);
316     rsUiDirector->SendMessages();
317     sleep(SLEEP_DURATION_LARGE);
318 
319     cout << "rs local surface demo cratePixelMap" << endl;
320     std::shared_ptr<MySurfaceCaptureCallback> mySurfaceCaptureCallback =
321         std::make_shared<MySurfaceCaptureCallback>();
322     cout << "windowsurfacenode id is " << surfaceNode->GetId() << endl;
323     RSSurfaceCaptureConfig captureConfig;
324     RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, mySurfaceCaptureCallback, captureConfig);
325     sleep(SLEEP_DURATION);
326 
327     float blurRadius = BLUR_RADIUS_NEGATIVE;
328     RSInterfaces::GetInstance().TakeSurfaceCaptureWithBlur(
329         surfaceNode, mySurfaceCaptureCallback, captureConfig, blurRadius);
330     sleep(SLEEP_DURATION);
331 
332     blurRadius = BLUR_RADIUS_SMALL;
333     RSInterfaces::GetInstance().TakeSurfaceCaptureWithBlur(
334         surfaceNode, mySurfaceCaptureCallback, captureConfig, blurRadius);
335     sleep(SLEEP_DURATION);
336 
337     blurRadius = BLUR_RADIUS_LARGE;
338     RSInterfaces::GetInstance().TakeSurfaceCaptureWithBlur(
339         surfaceNode, mySurfaceCaptureCallback, captureConfig, blurRadius);
340     sleep(SLEEP_DURATION);
341 
342     surfaceNode->SetSecurityLayer(true);
343     RSTransaction::FlushImplicitTransaction();
344     sleep(SLEEP_DURATION);
345     RSInterfaces::GetInstance().TakeSurfaceCapture(surfaceNode, mySurfaceCaptureCallback, captureConfig);
346     sleep(SLEEP_DURATION);
347 
348     RSInterfaces::GetInstance().TakeSurfaceCaptureWithBlur(
349         surfaceNode, mySurfaceCaptureCallback, captureConfig, blurRadius);
350     sleep(SLEEP_DURATION);
351 #endif
352     return 0;
353 }
354