• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "dm/display_manager.h"
23 #include "draw/canvas.h"
24 #include "draw/color.h"
25 #include "graphic_common.h"
26 #include "image/bitmap.h"
27 #include "image_source.h"
28 #include "include/core/SkColor.h"
29 #include "nativetoken_kit.h"
30 #include "pixel_map.h"
31 #include "png.h"
32 #include "render_context/render_context.h"
33 #include "surface_type.h"
34 #include "token_setproc.h"
35 #include "transaction/rs_interfaces.h"
36 #include "transaction/rs_transaction.h"
37 #include "ui/rs_canvas_drawing_node.h"
38 #include "ui/rs_canvas_node.h"
39 #include "ui/rs_display_node.h"
40 #include "ui/rs_effect_node.h"
41 #include "ui/rs_root_node.h"
42 #include "ui/rs_surface_extractor.h"
43 #include "ui/rs_surface_node.h"
44 #include "ui/rs_texture_export.h"
45 #include "ui/rs_ui_director.h"
46 #include "window.h"
47 
48 using namespace OHOS;
49 using namespace OHOS::Rosen;
50 using namespace OHOS::Rosen::Drawing;
51 using namespace std;
52 uint64_t screenId = 0;
53 
54 using WriteToPngParam = struct {
55     uint32_t width;
56     uint32_t height;
57     uint32_t stride;
58     uint32_t bitDepth;
59     const uint8_t *data;
60 };
61 
62 constexpr int BITMAP_DEPTH = 8;
63 
64 shared_ptr<RSNode> rootNode;
65 shared_ptr<RSCanvasNode> canvasNode;
66 shared_ptr<RSCanvasNode> canvasNode2;
67 shared_ptr<RSSurfaceNode> surfaceNode1;
68 shared_ptr<RSSurfaceNode> surfaceNode2;
69 shared_ptr<RSEffectNode> effectNode;
70 shared_ptr<RSCanvasDrawingNode> canvasDrawingNode;
71 shared_ptr<RSNode> myLittleRootNode;
72 
73 #ifdef RS_ENABLE_GPU
74     RenderContext* rc_ = nullptr;
75 #endif
76 
WriteToPng(const string & fileName,const WriteToPngParam & param)77 bool WriteToPng(const string &fileName, const WriteToPngParam &param)
78 {
79     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
80     if (pngStruct == nullptr) {
81         cout << "png_create_write_struct error, nullptr!" << endl;
82         return false;
83     }
84     png_infop pngInfo = png_create_info_struct(pngStruct);
85     if (pngInfo == nullptr) {
86         cout << "png_create_info_struct error, nullptr!" <<endl;
87         png_destroy_write_struct(&pngStruct, nullptr);
88         return false;
89     }
90     FILE *fp = fopen(fileName.c_str(), "wb");
91     if (fp == nullptr) {
92         cout << "open file error, nullptr!" << endl;
93         png_destroy_write_struct(&pngStruct, &pngInfo);
94         return false;
95     }
96     png_init_io(pngStruct, fp);
97 
98     // set png header
99     png_set_IHDR(pngStruct, pngInfo,
100         param.width, param.height,
101         param.bitDepth,
102         PNG_COLOR_TYPE_RGBA,
103         PNG_INTERLACE_NONE,
104         PNG_COMPRESSION_TYPE_BASE,
105         PNG_FILTER_TYPE_BASE);
106     png_set_packing(pngStruct); // set packing info
107     png_write_info(pngStruct, pngInfo); // write to header
108 
109     for (uint32_t i = 0; i < param.height; i++) {
110         png_write_row(pngStruct, param.data + (i * param.stride));
111     }
112 
113     png_write_end(pngStruct, pngInfo);
114 
115     // free
116     png_destroy_write_struct(&pngStruct, &pngInfo);
117     int ret = fclose(fp);
118     if (ret != 0) {
119         cout << "close fp failed" << endl;
120     }
121     return true;
122 }
123 
RenderContextInit()124 void RenderContextInit()
125 {
126 #ifdef RS_ENABLE_GPU
127     cout << "RS_ENABLE_GPU is true" << endl;
128     cout << "Init RenderContext start" << endl;
129     rc_ = RenderContextFactory::GetInstance().CreateEngine();
130     if (rc_) {
131         cout << "Init RenderContext success" << endl;
132         rc_->InitializeEglContext();
133     } else {
134         cout << "Init RenderContext failed, RenderContext is nullptr" << endl;
135     }
136 #endif
137 }
138 
DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)139 void DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)
140 {
141     int surfaceX = 100;
142     int surfaceY = 50;
143     int surfaceWidth = 300;
144     int surfaceHeight = 600;
145     SkRect surfaceGeometry = SkRect::MakeXYWH(surfaceX, surfaceY, surfaceWidth, surfaceHeight);
146     auto x = surfaceGeometry.x();
147     auto y = surfaceGeometry.y();
148     auto width = surfaceGeometry.width();
149     auto height = surfaceGeometry.height();
150     surfaceNode->SetBounds(x, y, width, height);
151     shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
152     if (rsSurface == nullptr) {
153         cout << "surface is nullptr" << endl;
154         return;
155     }
156 #ifdef RS_ENABLE_GPU
157     if (rc_) {
158         rsSurface->SetRenderContext(rc_);
159     } else {
160         cout << "DrawSurface: RenderContext is nullptr" << endl;
161     }
162 #endif
163     auto framePtr = rsSurface->RequestFrame(width, height);
164     if (!framePtr) {
165         cout << "framePtr is nullptr" << endl;
166         return;
167     }
168     auto canvas = framePtr->GetCanvas();
169     if (!canvas) {
170         cout << "canvas is nullptr" << endl;
171         return;
172     }
173     canvas->Clear(SK_ColorWHITE);
174 
175     Brush brush;
176     brush.SetColor(SK_ColorGREEN);
177     brush.SetAntiAlias(true);
178 
179     Font font = Font();
180     font.SetSize(16); // text size 16
181     std::shared_ptr<TextBlob> scaleInfoTextBlob = TextBlob::MakeFromString("Hello World",
182         font, TextEncoding::UTF8);
183     canvas->AttachBrush(brush);
184     int startpointX = 20;
185     int startpointY = 50;
186     canvas->DrawTextBlob(scaleInfoTextBlob.get(), startpointX, startpointY); // start point is (20, 50)
187     canvas->DetachBrush();
188     framePtr->SetDamageRegion(0, 0, width, height);
189     rsSurface->FlushFrame(framePtr);
190     return;
191 }
192 
WriteToPngWithPixelMap(const string & fileName,Media::PixelMap & pixelMap)193 bool WriteToPngWithPixelMap(const string &fileName, Media::PixelMap &pixelMap)
194 {
195     WriteToPngParam param;
196     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
197     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
198     param.data = pixelMap.GetPixels();
199     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
200     param.bitDepth = BITMAP_DEPTH;
201     return WriteToPng(fileName, param);
202 }
203 
DecodePixelMap(const string & pathName,const Media::AllocatorType & allocatorType)204 shared_ptr<Media::PixelMap> DecodePixelMap(const string& pathName, const Media::AllocatorType& allocatorType)
205 {
206     cout << "decode start: ------------ " << pathName << endl;
207     cout << "decode 1: CreateImageSource" << endl;
208     uint32_t errCode = 0;
209     std::unique_ptr<Media::ImageSource> imageSource =
210         Media::ImageSource::CreateImageSource(pathName, Media::SourceOptions(), errCode);
211     if (imageSource == nullptr || errCode != 0) {
212         cout << "imageSource : " << (imageSource != nullptr) << ", err:" << errCode << std::endl;
213         return nullptr;
214     }
215 
216     cout << "decode 2: CreatePixelMap" << endl;
217     Media::DecodeOptions decodeOpt;
218     decodeOpt.allocatorType = allocatorType;
219     shared_ptr<Media::PixelMap> pixelmap = imageSource->CreatePixelMap(decodeOpt, errCode);
220     if (pixelmap == nullptr || errCode != 0) {
221         cout << "pixelmap == nullptr, err:" << errCode << endl;
222         return nullptr;
223     }
224 
225     cout << "w x h: " << pixelmap->GetWidth() << "x" << pixelmap->GetHeight() << endl;
226     cout << "AllocatorType: " << (int)pixelmap->GetAllocatorType() << endl;
227     cout << "fd: " << (!pixelmap->GetFd() ? "null" : to_string(*(int*)pixelmap->GetFd())) << endl;
228     cout << "decode success: ------------ " << endl;
229     return pixelmap;
230 }
231 
232 class MySurfaceCaptureCallback : public SurfaceCaptureCallback {
233 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap)234     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
235     {
236         static int32_t count = 0;
237         if (pixelmap == nullptr) {
238             cout << "RSUIDirector::LocalCapture failed to get pixelmap, return nullptr!" << endl;
239             return;
240         }
241         cout << "rs local surface demo drawPNG" << endl;
242         string filename = "/data/local/test_" + to_string(count++) + ".jpg";
243         int ret = WriteToPngWithPixelMap(filename, *pixelmap);
244         if (!ret) {
245             cout << "pixelmap write to png failed" << endl;
246         }
247         cout << "pixelmap write to png sucess" << endl;
248     }
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> pixelMapHDR)249     void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
250         std::shared_ptr<Media::PixelMap> pixelMapHDR) override {}
251 };
252 
InitNativeTokenInfo()253 void InitNativeTokenInfo()
254 {
255     uint64_t tokenId;
256     const char *perms[1];
257     perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
258     NativeTokenInfoParams infoInstance = {
259         .dcapsNum = 0,
260         .permsNum = 1,
261         .aclsNum = 0,
262         .dcaps = NULL,
263         .perms = perms,
264         .acls = NULL,
265         .processName = "rs_uni_render_pixelmap_demo",
266         .aplStr = "system_basic",
267     };
268     tokenId = GetAccessTokenId(&infoInstance);
269     SetSelfTokenID(tokenId);
270     Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
271 }
272 
Init(shared_ptr<RSUIDirector> rsUiDirector,int width,int height)273 void Init(shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
274 {
275     cout << "rs local capture range demo Init Rosen Backend!" << endl;
276 
277     rootNode = RSRootNode::Create();
278     rootNode->SetBounds(0, 0, width, height);
279     rootNode->SetFrame(0, 0, width, height);
280     rootNode->SetBackgroundColor(SK_ColorRED);
281 
282     rsUiDirector->SetRSRootNode(rootNode->ReinterpretCastTo<RSRootNode>());
283     canvasNode = RSCanvasNode::Create();
284     canvasNode->SetBounds(10, 10, 600, 1000);
285     canvasNode->SetFrame(10, 10, 600, 1000);
286     canvasNode->SetBackgroundColor(SK_ColorYELLOW);
287     rootNode->AddChild(canvasNode, -1);
288 
289     canvasNode2 = RSCanvasNode::Create();
290     canvasNode2->SetBounds(5, 5, 400, 800);
291     canvasNode2->SetFrame(5, 5, 400, 800);
292     canvasNode2->SetBackgroundColor(SK_ColorBLUE);
293     canvasNode->AddChild(canvasNode2, -1);
294 
295     RSSurfaceNodeConfig config;
296     surfaceNode1 = RSSurfaceNode::Create(config, false);
297     RenderContextInit();
298     DrawSurfaceNode(surfaceNode1);
299     canvasNode2->AddChild(surfaceNode1, -1);
300 
301     effectNode = RSEffectNode::Create();
302     effectNode->SetBounds(5, 5, 250, 550);
303     effectNode->SetFrame(5, 5, 250, 550);
304     effectNode->SetBackgroundColor(SK_ColorRED);
305     surfaceNode1->AddChild(effectNode, -1);
306 
307     myLittleRootNode = RSRootNode::Create();
308     myLittleRootNode->SetBounds(5, 5, 200, 500);
309     myLittleRootNode->SetFrame(5, 5, 200, 500);
310     myLittleRootNode->SetBackgroundColor(SK_ColorYELLOW);
311     surfaceNode1->AddChild(myLittleRootNode, -1);
312 
313     canvasDrawingNode = RSCanvasDrawingNode::Create();
314     canvasDrawingNode->SetBounds(5, 5, 100, 300);
315     canvasDrawingNode->SetFrame(5, 5, 100, 300);
316     canvasDrawingNode->SetBackgroundColor(SK_ColorGREEN);
317     myLittleRootNode->AddChild(canvasDrawingNode, -1);
318 }
319 
320 class MyOffscreenRenderCallback : public SurfaceCaptureCallback {
321 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap)322     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
323     {
324         if (pixelmap == nullptr) {
325             cout << "RSUIDirector::LocalCapture failed to get pixelmap, return nullptr!" << endl;
326             return;
327         }
328         cout << "rs local surface demo drawPNG" << endl;
329         int ret = WriteToPngWithPixelMap("/data/local/test.jpg", *pixelmap);
330         if (!ret) {
331             cout << "pixelmap write to png failed" << endl;
332         }
333         cout << "pixelmap write to png success" << endl;
334     }
OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,std::shared_ptr<Media::PixelMap> pixelMapHDR)335     void OnSurfaceCaptureHDR(std::shared_ptr<Media::PixelMap> pixelMap,
336         std::shared_ptr<Media::PixelMap> pixelMapHDR) override {}
337 };
338 
main()339 int main()
340 {
341     InitNativeTokenInfo();
342 
343     cout << "rs local capture range demo" << endl;
344     DisplayId displayId = DisplayManager::GetInstance().GetDefaultDisplayId();
345     RSSurfaceNodeConfig surfaceNodeConfig;
346     surfaceNodeConfig.SurfaceNodeName = "capture_range_demo";
347     RSSurfaceNodeType surfaceNodeType = RSSurfaceNodeType::APP_WINDOW_NODE;
348     cout << "RSSurfaceNode:: Create" << endl;
349     auto surfaceNode = RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
350     if (!surfaceNode) {
351         return -1;
352     }
353     surfaceNode->SetBounds(0, 0, 1260, 2720);
354     surfaceNode->SetFrame(0, 0, 1260, 2720);
355     surfaceNode->SetPositionZ(RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
356     cout << "GetDisplayId: " << endl;
357     screenId = DisplayManager::GetInstance().GetDisplayById(displayId)->GetId();
358     cout << "ScreenId: " << screenId << endl;
359     surfaceNode->AttachToDisplay(screenId);
360 
361     auto rsUiDirector = RSUIDirector::Create();
362     rsUiDirector->Init();
363     RSTransaction::FlushImplicitTransaction();
364     cout << "rs local capture range demo init" << endl;
365     rsUiDirector->SetRSSurfaceNode(surfaceNode);
366 
367     Init(rsUiDirector, 1260, 2720);
368     RSTransaction::FlushImplicitTransaction();
369     sleep(4);
370 
371     cout << "rs local capture range demo createPixelmap" << endl;
372     std::shared_ptr<MySurfaceCaptureCallback> mySurfaceCaptureCallback =
373         std::make_shared<MySurfaceCaptureCallback>();
374     cout << "rootNode id is " << rootNode->GetId() << endl;
375 
376     // 1. red, yellow
377     RSInterfaces::GetInstance().TakeUICaptureInRange(
378         rootNode, canvasNode, true, mySurfaceCaptureCallback, 1, 1, false);
379     cout << "1. red, yellow, start: root -> end: canvas1" << endl;
380     sleep(2);
381 
382     // 2. red, yellow, blue
383     RSInterfaces::GetInstance().TakeUICaptureInRange(
384         rootNode, canvasNode2, true, mySurfaceCaptureCallback, 1, 1, false);
385     cout << "2. red, yellow, blue, start: root -> canvas1 -> end: canvas2" << endl;
386     sleep(2);
387 
388     // 3. yellow...
389     RSInterfaces::GetInstance().TakeUICaptureInRange(
390         canvasNode, rootNode, true, mySurfaceCaptureCallback, 1, 1, false);
391     cout << "3. yellow..., start: canvas1 -> end: root" << endl;
392     sleep(2);
393 
394     // 4. blue
395     RSInterfaces::GetInstance().TakeUICaptureInRange(
396         canvasNode2, canvasNode2, true, mySurfaceCaptureCallback, 1, 1, false);
397     cout << "4.blue, start: canvas2 -> end: canvas2" << endl;
398     sleep(2);
399 
400     // 5. red...
401     RSInterfaces::GetInstance().TakeUICaptureInRange(
402         rootNode, nullptr, true, mySurfaceCaptureCallback, 1, 1, false);
403     cout << "5. red, yellow, blue, yellow, green, start: root -> end: nullptr" << endl;
404     sleep(2);
405     return 0;
406 }