• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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 
60 shared_ptr<RSNode> rootNode;
61 shared_ptr<RSCanvasNode> canvasNode;
62 shared_ptr<RSCanvasNode> canvasNode2;
63 shared_ptr<RSSurfaceNode> surfaceNode1;
64 shared_ptr<RSSurfaceNode> surfaceNode2;
65 
66 #ifdef RS_ENABLE_GPU
67     RenderContext* rc_ = nullptr;
68 #endif
69 
WriteToPng(const string & fileName,const WriteToPngParam & param)70 bool WriteToPng(const string &fileName, const WriteToPngParam &param)
71 {
72     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
73     if (pngStruct == nullptr) {
74         cout << "png_create_write_struct error, nullptr!" << endl;
75         return false;
76     }
77     png_infop pngInfo = png_create_info_struct(pngStruct);
78     if (pngInfo == nullptr) {
79         cout << "png_create_info_struct error, nullptr!" <<endl;
80         png_destroy_write_struct(&pngStruct, nullptr);
81         return false;
82     }
83     FILE *fp = fopen(fileName.c_str(), "wb");
84     if (fp == nullptr) {
85         cout << "open file error, nullptr!" << endl;
86         png_destroy_write_struct(&pngStruct, &pngInfo);
87         return false;
88     }
89     png_init_io(pngStruct, fp);
90 
91     // set png header
92     png_set_IHDR(pngStruct, pngInfo,
93         param.width, param.height,
94         param.bitDepth,
95         PNG_COLOR_TYPE_RGBA,
96         PNG_INTERLACE_NONE,
97         PNG_COMPRESSION_TYPE_BASE,
98         PNG_FILTER_TYPE_BASE);
99     png_set_packing(pngStruct); // set packing info
100     png_write_info(pngStruct, pngInfo); // write to header
101 
102     for (uint32_t i = 0; i < param.height; i++) {
103         png_write_row(pngStruct, param.data + (i * param.stride));
104     }
105 
106     png_write_end(pngStruct, pngInfo);
107 
108     // free
109     png_destroy_write_struct(&pngStruct, &pngInfo);
110     int ret = fclose(fp);
111     if (ret != 0) {
112         cout << "close fp failed" << endl;
113     }
114     return true;
115 }
116 
RenderContextInit()117 void RenderContextInit()
118 {
119 #ifdef RS_ENABLE_GPU
120     cout << "RS_ENABLE_GPU is true" << endl;
121     cout << "Init RenderContext start" << endl;
122     rc_ = RenderContextFactory::GetInstance().CreateEngine();
123     if (rc_) {
124         cout << "Init RenderContext success" << endl;
125         rc_->InitializeEglContext();
126     } else {
127         cout << "Init RenderContext failed, RenderContext is nullptr" << endl;
128     }
129 #endif
130 }
131 
DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)132 void DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)
133 {
134     SkRect surfaceGeometry = SkRect::MakeXYWH(100, 50, 300, 600);
135     auto x = surfaceGeometry.x();
136     auto y = surfaceGeometry.y();
137     auto width = surfaceGeometry.width();
138     auto height = surfaceGeometry.height();
139     surfaceNode->SetBounds(x, y, width, height);
140     shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
141     if (rsSurface == nullptr) {
142         cout << "surface is nullptr" << endl;
143         return;
144     }
145 #ifdef RS_ENABLE_GPU
146     if (rc_) {
147         rsSurface->SetRenderContext(rc_);
148     } else {
149         cout << "DrawSurface: RenderContext is nullptr" << endl;
150     }
151 #endif
152     auto framePtr = rsSurface->RequestFrame(width, height);
153     if (!framePtr) {
154         cout << "framePtr is nullptr" << endl;
155         return;
156     }
157     auto canvas = framePtr->GetCanvas();
158     if (!canvas) {
159         cout << "canvas is nullptr" << endl;
160         return;
161     }
162     canvas->Clear(SK_ColorWHITE);
163 
164     Brush brush;
165     brush.SetColor(SK_ColorGREEN);
166     brush.SetAntiAlias(true);
167 
168     string scaleInfo = "Hello World";
169     Font font = Font();
170     font.SetSize(16); // text size 16
171     std::shared_ptr<TextBlob> scaleInfoTextBlob = TextBlob::MakeFromString(scaleInfo.c_str(),
172         font, TextEncoding::UTF8);
173     canvas->AttachBrush(brush);
174     canvas->DrawTextBlob(scaleInfoTextBlob.get(), 20, 50); // start point is (20, 50)
175     canvas->DetachBrush();
176     framePtr->SetDamageRegion(0, 0, width, height);
177     rsSurface->FlushFrame(framePtr);
178     return;
179 }
180 
WriteToPngWithPixelMap(const string & fileName,Media::PixelMap & pixelMap)181 bool WriteToPngWithPixelMap(const string &fileName, Media::PixelMap &pixelMap)
182 {
183     WriteToPngParam param;
184     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
185     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
186     param.data = pixelMap.GetPixels();
187     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
188     param.bitDepth = BITMAP_DEPTH;
189     return WriteToPng(fileName, param);
190 }
191 
Init(shared_ptr<RSUIDirector> rsUiDirector,int width,int height)192 void Init(shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
193 {
194     cout << "rs local surface capture demo Init Rosen Backend!" << endl;
195 
196     rootNode = RSRootNode::Create();
197     rootNode->SetBounds(0, 0, width, height);
198     rootNode->SetFrame(0, 0, width, height);
199     rootNode->SetBackgroundColor(SK_ColorRED);
200 
201     rsUiDirector->SetRoot(rootNode->GetId());
202     canvasNode = RSCanvasNode::Create();
203     canvasNode->SetBounds(10, 10, 600, 1000);
204     canvasNode->SetFrame(10, 10, 600, 1000);
205     canvasNode->SetBackgroundColor(SK_ColorYELLOW);
206     rootNode->AddChild(canvasNode, -1);
207 
208     canvasNode2 = RSCanvasNode::Create();
209     canvasNode2->SetBounds(5, 5, 400, 800);
210     canvasNode2->SetFrame(5, 5, 400, 800);
211     canvasNode2->SetBackgroundColor(SK_ColorBLUE);
212     canvasNode->AddChild(canvasNode2, -1);
213 
214     RSSurfaceNodeConfig config;
215     surfaceNode1 = RSSurfaceNode::Create(config, false);
216     RenderContextInit();
217     DrawSurfaceNode(surfaceNode1);
218     canvasNode2->AddChild(surfaceNode1, -1);
219 }
220 
221 class MyOffscreenRenderCallback : public SurfaceCaptureCallback {
222 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap)223     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
224     {
225         if (pixelmap == nullptr) {
226             cout << "RSUIDirector::LocalCapture failed to get pixelmap, return nullptr!" << endl;
227             return;
228         }
229         cout << "rs local surface demo drawPNG" << endl;
230         int ret = WriteToPngWithPixelMap("/data/local/test.jpg", *pixelmap);
231         if (!ret) {
232             cout << "pixelmap write to png failed" << endl;
233         }
234         cout << "pixelmap write to png sucess" << endl;
235     }
236 };
237 
InitNativeTokenInfo()238 void InitNativeTokenInfo()
239 {
240 #ifdef SUPPORT_ACCESS_TOKEN
241     uint64_t tokenId;
242     const char *perms[1];
243     perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
244     NativeTokenInfoParams infoInstance = {
245         .dcapsNum = 0,
246         .permsNum = 1,
247         .aclsNum = 0,
248         .dcaps = NULL,
249         .perms = perms,
250         .acls = NULL,
251         .processName = "rs_uni_render_pixelmap_demo",
252         .aplStr = "system_basic",
253     };
254     tokenId = GetAccessTokenId(&infoInstance);
255     SetSelfTokenID(tokenId);
256     Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
257 #endif
258 }
259 
main()260 int main()
261 {
262 #ifdef SUPPORT_ACCESS_TOKEN
263     InitNativeTokenInfo();
264 
265     cout << "rs local surface capture demo" << endl;
266     sptr<WindowOption> option = new WindowOption();
267     option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
268     option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
269     option->SetWindowRect({0, 0, 680, 1100});
270     string demoName = "offscreen_render_demo";
271     auto window = Window::Create(demoName, option);
272 
273     window->Show();
274     sleep(2);
275     auto rect = window->GetRect();
276     while (rect.width_ == 0 && rect.height_ == 0) {
277         cout << "rs local surface demo create window failed: " << rect.width_ << " " << rect.height_ << endl;
278         window->Hide();
279         window->Destroy();
280         window = Window::Create(demoName, option);
281         window->Show();
282         rect = window->GetRect();
283     }
284     cout << "rs local surface demo create window success: " << rect.width_ << " " << rect.height_ << endl;
285     auto surfaceNode = window->GetSurfaceNode();
286 
287     auto rsUiDirector = RSUIDirector::Create();
288     rsUiDirector->Init();
289     RSTransaction::FlushImplicitTransaction();
290 
291     cout << "rs local surface demo init" << endl;
292     rsUiDirector->SetRSSurfaceNode(surfaceNode);
293     Init(rsUiDirector, rect.width_, rect.height_);
294     rsUiDirector->SendMessages();
295     sleep(4);
296 
297     cout << "rs local surface demo cratePixelMap" << endl;
298     std::shared_ptr<MyOffscreenRenderCallback> myOffscreenRenderCallback =
299         std::make_shared<MyOffscreenRenderCallback>();
300     cout << "rootNode id is" << rootNode->GetId() << endl;
301     RSInterfaces::GetInstance().TakeSurfaceCaptureForUI(rootNode, myOffscreenRenderCallback, 1, 1);
302     sleep(2);
303     rootNode->RemoveFromTree();
304     RSInterfaces::GetInstance().TakeSurfaceCaptureForUI(rootNode, myOffscreenRenderCallback, 1, 1);
305     sleep(2);
306 #endif
307     return 0;
308 }
309