• 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 "display_type.h"
22 #include "draw/canvas.h"
23 #include "draw/color.h"
24 #include "graphic_common.h"
25 #include "image/bitmap.h"
26 #include "include/core/SkColor.h"
27 #include "include/core/SkTextBlob.h"
28 #include "pixel_map.h"
29 #include "png.h"
30 #include "render_context/render_context.h"
31 #include "surface_type.h"
32 #include "transaction/rs_interfaces.h"
33 #include "transaction/rs_transaction.h"
34 #include "ui/rs_display_node.h"
35 #include "ui/rs_ui_director.h"
36 #include "ui/rs_root_node.h"
37 #include "ui/rs_surface_node.h"
38 #include "ui/rs_surface_extractor.h"
39 #include "window.h"
40 
41 using namespace OHOS;
42 using namespace OHOS::Rosen;
43 using namespace OHOS::Rosen::Drawing;
44 using namespace std;
45 
46 using WriteToPngParam = struct {
47     uint32_t width;
48     uint32_t height;
49     uint32_t stride;
50     uint32_t bitDepth;
51     const uint8_t *data;
52 };
53 
54 constexpr int BITMAP_DEPTH = 8;
55 
56 shared_ptr<RSNode> rootNode;
57 shared_ptr<RSCanvasNode> canvasNode;
58 shared_ptr<RSCanvasNode> canvasNode2;
59 shared_ptr<RSSurfaceNode> surfaceNode1;
60 shared_ptr<RSSurfaceNode> surfaceNode2;
61 
62 #ifdef ACE_ENABLE_GPU
63     RenderContext* rc_ = nullptr;
64 #endif
65 
WriteToPng(const string & fileName,const WriteToPngParam & param)66 bool WriteToPng(const string &fileName, const WriteToPngParam &param)
67 {
68     png_structp pngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
69     if (pngStruct == nullptr) {
70         cout << "png_create_write_struct error, nullptr!" << endl;
71         return false;
72     }
73     png_infop pngInfo = png_create_info_struct(pngStruct);
74     if (pngInfo == nullptr) {
75         cout << "png_create_info_struct error, nullptr!" <<endl;
76         png_destroy_write_struct(&pngStruct, nullptr);
77         return false;
78     }
79     FILE *fp = fopen(fileName.c_str(), "wb");
80     if (fp == nullptr) {
81         cout << "open file error, nullptr!" << endl;
82         png_destroy_write_struct(&pngStruct, &pngInfo);
83         return false;
84     }
85     png_init_io(pngStruct, fp);
86 
87     // set png header
88     png_set_IHDR(pngStruct, pngInfo,
89         param.width, param.height,
90         param.bitDepth,
91         PNG_COLOR_TYPE_RGBA,
92         PNG_INTERLACE_NONE,
93         PNG_COMPRESSION_TYPE_BASE,
94         PNG_FILTER_TYPE_BASE);
95     png_set_packing(pngStruct); // set packing info
96     png_write_info(pngStruct, pngInfo); // write to header
97 
98     for (uint32_t i = 0; i < param.height; i++) {
99         png_write_row(pngStruct, param.data + (i * param.stride));
100     }
101 
102     png_write_end(pngStruct, pngInfo);
103 
104     // free
105     png_destroy_write_struct(&pngStruct, &pngInfo);
106     int ret = fclose(fp);
107     if (ret != 0) {
108         cout << "close fp failed" << endl;
109     }
110     return true;
111 }
112 
RenderContextInit()113 void RenderContextInit()
114 {
115 #ifdef ACE_ENABLE_GPU
116     cout << "ACE_ENABLE_GPU is true" << endl;
117     cout << "Init RenderContext start" << endl;
118     rc_ = RenderContextFactory::GetInstance().CreateEngine();
119     if (rc_) {
120         cout << "Init RenderContext success" << endl;
121         rc_->InitializeEglContext();
122     } else {
123         cout << "Init RenderContext failed, RenderContext is nullptr" << endl;
124     }
125 #endif
126 }
127 
DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)128 void DrawSurfaceNode(shared_ptr<RSSurfaceNode> surfaceNode)
129 {
130     SkRect surfaceGeometry = SkRect::MakeXYWH(100, 50, 300, 600);
131     auto x = surfaceGeometry.x();
132     auto y = surfaceGeometry.y();
133     auto width = surfaceGeometry.width();
134     auto height = surfaceGeometry.height();
135     surfaceNode->SetBounds(x, y, width, height);
136     shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(surfaceNode);
137     if (rsSurface == nullptr) {
138         cout << "surface is nullptr" << endl;
139         return;
140     }
141 #ifdef ACE_ENABLE_GPU
142     if (rc_) {
143         rsSurface->SetRenderContext(rc_);
144     } else {
145         cout << "DrawSurface: RenderContext is nullptr" << endl;
146     }
147 #endif
148     auto framePtr = rsSurface->RequestFrame(width, height);
149     if (!framePtr) {
150         cout << "framePtr is nullptr" << endl;
151         return;
152     }
153     auto canvas = framePtr->GetCanvas();
154     if (!canvas) {
155         cout << "canvas is nullptr" << endl;
156         return;
157     }
158     canvas->clear(SK_ColorWHITE);
159     SkPaint paint;
160     paint.setAntiAlias(true);
161     paint.setStyle(SkPaint::kFill_Style);
162     paint.setStrokeWidth(20);
163     paint.setStrokeJoin(SkPaint::kRound_Join);
164     paint.setColor(SK_ColorGREEN);
165 
166     string scaleInfo = "Hello World";
167     sk_sp<SkTextBlob> scaleInfoTextBlob = SkTextBlob::MakeFromString(
168         scaleInfo.c_str(), SkFont(nullptr, 16.0f, 1.0f, 0.0f)); // font size: 16
169     canvas->drawTextBlob(scaleInfoTextBlob.get(), 20, 50, paint); // start point is (20, 50)
170     framePtr->SetDamageRegion(0, 0, width, height);
171     rsSurface->FlushFrame(framePtr);
172     return;
173 }
174 
WriteToPngWithPixelMap(const string & fileName,Media::PixelMap & pixelMap)175 bool WriteToPngWithPixelMap(const string &fileName, Media::PixelMap &pixelMap)
176 {
177     WriteToPngParam param;
178     param.width = static_cast<uint32_t>(pixelMap.GetWidth());
179     param.height = static_cast<uint32_t>(pixelMap.GetHeight());
180     param.data = pixelMap.GetPixels();
181     param.stride = static_cast<uint32_t>(pixelMap.GetRowBytes());
182     param.bitDepth = BITMAP_DEPTH;
183     return WriteToPng(fileName, param);
184 }
185 
Init(shared_ptr<RSUIDirector> rsUiDirector,int width,int height)186 void Init(shared_ptr<RSUIDirector> rsUiDirector, int width, int height)
187 {
188     cout << "rs local surface capture demo Init Rosen Backend!" << endl;
189 
190     rootNode = RSRootNode::Create();
191     rootNode->SetBounds(0, 0, width, height);
192     rootNode->SetFrame(0, 0, width, height);
193     rootNode->SetBackgroundColor(SK_ColorRED);
194 
195     rsUiDirector->SetRoot(rootNode->GetId());
196     canvasNode = RSCanvasNode::Create();
197     canvasNode->SetBounds(10, 10, 600, 1000);
198     canvasNode->SetFrame(10, 10, 600, 1000);
199     canvasNode->SetBackgroundColor(SK_ColorYELLOW);
200     rootNode->AddChild(canvasNode, -1);
201 
202     canvasNode2 = RSCanvasNode::Create();
203     canvasNode2->SetBounds(5, 5, 400, 800);
204     canvasNode2->SetFrame(5, 5, 400, 800);
205     canvasNode2->SetBackgroundColor(SK_ColorBLUE);
206     canvasNode->AddChild(canvasNode2, -1);
207 
208     RSSurfaceNodeConfig config;
209     surfaceNode1 = RSSurfaceNode::Create(config, false);
210     RenderContextInit();
211     DrawSurfaceNode(surfaceNode1);
212     canvasNode2->AddChild(surfaceNode1, -1);
213 }
214 
215 class MyOffscreenRenderCallback : public SurfaceCaptureCallback {
216 public:
OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap)217     void OnSurfaceCapture(std::shared_ptr<Media::PixelMap> pixelmap) override
218     {
219         if (pixelmap == nullptr) {
220             cout << "RSUIDirector::LocalCapture failed to get pixelmap, return nullptr!" << endl;
221             return;
222         }
223         cout << "rs local surface demo drawPNG" << endl;
224         int ret = WriteToPngWithPixelMap("/data/local/test.jpg", *pixelmap);
225         if (!ret) {
226             cout << "pixelmap write to png failed" << endl;
227         }
228         cout << "pixelmap write to png sucess" << endl;
229     }
230 };
231 
main()232 int main()
233 {
234     cout << "rs local surface capture demo" << endl;
235     sptr<WindowOption> option = new WindowOption();
236     option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
237     option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
238     option->SetWindowRect({0, 0, 680, 1100});
239     string demoName = "offscreen_render_demo";
240     auto window = Window::Create(demoName, option);
241 
242     window->Show();
243     auto rect = window->GetRect();
244     while (rect.width_ == 0 && rect.height_ == 0) {
245         cout << "rs local surface demo create window failed: " << rect.width_ << " " << rect.height_ << endl;
246         window->Hide();
247         window->Destroy();
248         window = Window::Create(demoName, option);
249         window->Show();
250         rect = window->GetRect();
251     }
252     cout << "rs local surface demo create window success: " << rect.width_ << " " << rect.height_ << endl;
253     auto surfaceNode = window->GetSurfaceNode();
254 
255     auto rsUiDirector = RSUIDirector::Create();
256     rsUiDirector->Init();
257     RSTransaction::FlushImplicitTransaction();
258 
259     cout << "rs local surface demo init" << endl;
260     rsUiDirector->SetRSSurfaceNode(surfaceNode);
261     Init(rsUiDirector, rect.width_, rect.height_);
262     rsUiDirector->SendMessages();
263     sleep(4);
264 
265     cout << "rs local surface demo cratePixelMap" << endl;
266     std::shared_ptr<MyOffscreenRenderCallback> myOffscreenRenderCallback =
267         std::make_shared<MyOffscreenRenderCallback>();
268     cout << "rootNode id is" << rootNode->GetId() << endl;
269     RSInterfaces::GetInstance().TakeSurfaceCaptureForUI(rootNode, myOffscreenRenderCallback, 1, 1);
270     sleep(2);
271     rootNode->RemoveFromTree();
272     RSInterfaces::GetInstance().TakeSurfaceCaptureForUI(rootNode, myOffscreenRenderCallback, 1, 1);
273     sleep(2);
274     return 0;
275 }
276