1 /*
2  * Copyright (c) 2021 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 <cinttypes>
17 #include <cstdio>
18 #include <cstdlib>
19 #include <fstream>
20 #include <memory>
21 #include <securec.h>
22 #include <sstream>
23 #include <unistd.h>
24 
25 #include <sync_fence.h>
26 
27 #include <event_handler.h>
28 #include <surface.h>
29 #include "hdi_backend.h"
30 #include "hdi_layer.h"
31 #include "hdi_layer_info.h"
32 #include "hdi_output.h"
33 #include "hdi_screen.h"
34 
35 #include "draw/color.h"
36 #include "draw/brush.h"
37 #include "draw/canvas.h"
38 #include "draw/pen.h"
39 #include "draw/path.h"
40 #include "draw/clip.h"
41 #include "effect/path_effect.h"
42 #include "effect/shader_effect.h"
43 #include "image/bitmap.h"
44 #include "image/image.h"
45 #include "utils/rect.h"
46 
47 #include "utils/matrix.h"
48 #include "utils/camera3d.h"
49 
50 using namespace OHOS;
51 using namespace Rosen;
52 using namespace Drawing;
53 
54 namespace {
55 /*
56  * base layer: status bar/launcher/navigation bar
57  */
58 constexpr uint32_t BASE_LAYER_NUM = 3;
59 }
60 
61 class HelloDrawing : public IBufferConsumerListenerClazz {
62 public:
63     void Init(uint32_t width, uint32_t height, HdiBackend* backend);
64     void DoDrawData(void *image, uint32_t width, uint32_t height);
65     void DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index);
66     void Draw();
67     void DrawSurface();
68     void Sync(int64_t, void *data);
69     void CreatePyhsicalScreen();
70     void DoPrepareCompleted(sptr<Surface>& surface, const struct PrepareCompleteParam &param);
71     void OnBufferAvailable() override;
72     SurfaceError ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width,
73                                uint32_t height, uint32_t index, bool baseLayer);
74     bool FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index, uint32_t zorder,
75                        GraphicIRect &dstRect);
76     bool DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec);
77     void CreateBaseSurface(uint32_t index);
78     void OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected);
79 
80     void TestDrawPathPro(Canvas &canvas, uint32_t width, uint32_t height);
81     void TestDrawImage(Canvas &canvas, uint32_t width, uint32_t height);
82 
83     uint32_t freq_ = 30;
84     uint32_t width_ = 0;
85     uint32_t height_ = 0;
86 
87     uint32_t display_w = 480;
88     uint32_t display_h = 960;
89 
90     bool initDeviceFinished_ = false;
91     bool deviceConnected_ = false;
92     std::shared_ptr<HdiOutput> output = nullptr;
93 
94 private:
95     uint32_t currentModeIndex_ = 0;
96     std::vector<GraphicDisplayModeInfo> displayModeInfos_;
97     std::vector<uint32_t> baseWidthVec_;
98     std::vector<uint32_t> baseHeightVec_;
99     std::unique_ptr<HdiScreen> screen = nullptr;
100 
101     std::vector<sptr<Surface>> basePSurfaceVec_;
102     std::vector<sptr<Surface>> baseCSurfaceVec_;
103 
104     HdiBackend* backend = nullptr;
105 
106     bool ready = false;
107 };
108 
OnBufferAvailable()109 void HelloDrawing::OnBufferAvailable()
110 {
111 }
112 
TestDrawPathPro(Canvas & canvas,uint32_t width,uint32_t height)113 void HelloDrawing::TestDrawPathPro(Canvas &canvas, uint32_t width, uint32_t height)
114 {
115     int len = 300;
116     Point a(500, 500); // point position
117 
118     Point c;
119     Point d;
120 
121     d.SetX(a.GetX() - len * std::sin(18.0f)); // degree is 18
122     d.SetY(a.GetY() + len * std::cos(18.0f)); // degree is 18
123 
124     c.SetX(a.GetX() + len * std::sin(18.0f)); // degree is 18
125     c.SetY(d.GetY());
126 
127     Point b;
128     b.SetX(a.GetX() + (len / 2.0));
129     b.SetY(a.GetY() + std::sqrt((c.GetX() - d.GetX()) * (c.GetX() - d.GetX()) + (len / 2.0) * (len / 2.0)));
130 
131     Point e;
132     e.SetX(a.GetX() - (len / 2.0));
133     e.SetY(b.GetY());
134 
135     Path path;
136     path.MoveTo(a.GetX(), a.GetY());
137     path.LineTo(b.GetX(), b.GetY());
138     path.LineTo(c.GetX(), c.GetY());
139     path.LineTo(d.GetX(), d.GetY());
140     path.LineTo(e.GetX(), e.GetY());
141     path.Close();
142 
143     Pen pen;
144     pen.SetAntiAlias(true);
145     pen.SetColor(Drawing::Color::COLOR_RED);
146     pen.SetWidth(10); // The thickness of the pen is 10
147     canvas.AttachPen(pen);
148 
149     Brush brush;
150     brush.SetColor(Drawing::Color::COLOR_BLUE);
151     canvas.AttachBrush(brush);
152 
153     canvas.DrawPath(path);
154 }
155 
TestDrawImage(Canvas & canvas,uint32_t width,uint32_t height)156 void HelloDrawing::TestDrawImage(Canvas& canvas, uint32_t width, uint32_t height)
157 {
158     LOGI("+++++++ TestDrawImage");
159     Bitmap bmp;
160     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
161     bmp.Build(300, 300, format); // bitmap width and height
162     bmp.ClearWithColor(Drawing::Color::COLOR_BLUE);
163 
164     Image image;
165     image.BuildFromBitmap(bmp);
166     int imageWidth = image.GetWidth();
167     int imageHeight = image.GetHeight();
168     LOGI("image width = %{public}d, image height = %{public}d", imageWidth, imageHeight);
169     Matrix matrix;
170     // Set matrix to rotate by degrees 45 about a pivot point at (0, 0).
171     matrix.Rotate(45, 0, 0);
172     auto e = ShaderEffect::CreateImageShader(image, TileMode::REPEAT, TileMode::MIRROR, SamplingOptions(), matrix);
173     auto c = Drawing::ColorSpace::CreateRefImage(image);
174 
175     Pen pen;
176     pen.SetAntiAlias(true);
177     pen.SetColor(Drawing::Color::COLOR_BLUE);
178     pen.SetColor(pen.GetColor4f(), c);
179     pen.SetWidth(10); // The thickness of the pen is 10
180     pen.SetShaderEffect(e);
181     canvas.AttachPen(pen);
182     canvas.DrawImage(image, 500, 500, SamplingOptions()); // draw image at (500,500)
183 
184     LOGI("------- TestDrawImage");
185 }
186 
DoDrawData(void * image,uint32_t width,uint32_t height)187 void HelloDrawing::DoDrawData(void *image, uint32_t width, uint32_t height)
188 {
189     Bitmap bitmap;
190     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
191     bitmap.Build(width, height, format);
192 
193     Canvas canvas;
194     canvas.Bind(bitmap);
195     canvas.Clear(Color::COLOR_WHITE);
196 
197     TestDrawImage(canvas, width, height);
198     constexpr uint32_t stride = 4;
199     int32_t addrSize = width * height * stride;
200     auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
201     if (ret != EOK) {
202         LOGE("memcpy_s failed");
203     }
204 }
205 
DoDrawBaseData(void * image,uint32_t width,uint32_t height,uint32_t index)206 void HelloDrawing::DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index)
207 {
208     Bitmap bitmap;
209     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUE};
210     bitmap.Build(width, height, format);
211 
212     Canvas canvas;
213     canvas.Bind(bitmap);
214     canvas.Clear(Color::COLOR_RED);
215     if (index == 1) {
216         canvas.Clear(Color::COLOR_WHITE);
217         TestDrawImage(canvas, width, height);
218     }
219     constexpr uint32_t stride = 4;
220     int32_t addrSize = width * height * stride;
221     auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
222     if (ret != EOK) {
223         LOGE("memcpy_s failed");
224     }
225 }
226 
ProduceBuffer(sptr<Surface> & produceSurface,uint32_t width,uint32_t height,uint32_t index,bool baseLayer)227 SurfaceError HelloDrawing::ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width,
228                                          uint32_t height, uint32_t index, bool baseLayer)
229 {
230     OHOS::sptr<SurfaceBuffer> buffer;
231     int32_t releaseFence = -1;
232     BufferRequestConfig config = {
233         .width = width,
234         .height = height,
235         .strideAlignment = 0x8,
236         .format = GRAPHIC_PIXEL_FMT_RGBA_8888,
237         .usage = produceSurface->GetDefaultUsage(),
238     };
239 
240     SurfaceError ret = produceSurface->RequestBuffer(buffer, releaseFence, config);
241     if (ret != 0) {
242         LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
243         return ret;
244     }
245 
246     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
247     tempFence->Wait(100); // 100ms
248 
249     if (buffer == nullptr) {
250         LOGE("%s: buffer is nullptr", __func__);
251         return SURFACE_ERROR_NULLPTR;
252     }
253 
254     LOGI("ProduceBuffer: width: %{public}d height:%{public}d stride:%{public}d size:%{public}d",
255         buffer->GetWidth(), buffer->GetHeight(), buffer->GetBufferHandle()->stride, buffer->GetSize());
256 
257     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
258     if (baseLayer) {
259         DoDrawBaseData(addr, buffer->GetWidth(), buffer->GetHeight(), index);
260     } else {
261         DoDrawData(addr, buffer->GetWidth(), buffer->GetHeight());
262     }
263 
264     BufferFlushConfig flushConfig = {
265         .damage = {
266             .w = width,
267             .h = height,
268         },
269     };
270 
271     int32_t acquireFence = -1;
272     ret = produceSurface->FlushBuffer(buffer, acquireFence, flushConfig);
273 
274     LOGI("Sync %{public}s", SurfaceErrorStr(ret).c_str());
275     return SURFACE_ERROR_OK;
276 }
277 
Draw()278 void HelloDrawing::Draw()
279 {
280     static int32_t count = 0;
281 
282     do {
283         std::vector<LayerInfoPtr> layerVec;
284         layerVec.resize(BASE_LAYER_NUM);
285         for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
286             std::shared_ptr<HdiLayerInfo> showLayer = HdiLayerInfo::CreateHdiLayerInfo();
287             layerVec[i] = showLayer;
288         }
289 
290         if (BASE_LAYER_NUM == 3) {
291             if (!DrawBaseLayer(layerVec)) {
292                 continue;
293             }
294         }
295 
296         output->SetLayerInfo(layerVec);
297 
298         GraphicIRect damageRect;
299         damageRect.x = 0; // Absolute coordinates, with offset
300         damageRect.y = 0;
301         damageRect.w = display_w;
302         damageRect.h = display_h;
303         std::vector<GraphicIRect> outputDamages;
304         outputDamages.emplace_back(damageRect);
305         output->SetOutputDamages(outputDamages);
306 
307         backend->Repaint(output);
308         for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
309             int32_t releaseFence = -1;
310             sptr<SyncFence> tempFence = new SyncFence(releaseFence);
311             baseCSurfaceVec_[i]->ReleaseBuffer(baseCSurfaceVec_[i]->GetBuffer(), tempFence);
312             tempFence->Wait(100); // 100 ms
313         }
314 
315         count++;
316 #ifdef DEBUG_DUMP
317         std::string result;
318         output->Dump(result);
319         LOGI("Dump layer result after ReleaseBuffer : %{public}s", result.c_str());
320 #endif
321     } while (false);
322 }
323 
DrawBaseLayer(std::vector<LayerInfoPtr> & layerVec)324 bool HelloDrawing::DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec)
325 {
326     // status bar
327     int32_t zorder = 1;
328     GraphicIRect dstRect;
329     dstRect.x = 0;  // Absolute coordinates, with offset
330     dstRect.y = 0;
331     dstRect.w = baseWidthVec_[0];
332     dstRect.h = baseHeightVec_[0];
333     if (!FillBaseLayer(layerVec[0], 0, zorder, dstRect)) {
334         return false;
335     }
336 
337     // launcher
338     zorder = 0;
339     dstRect.x = 0;  // Absolute coordinates, with offset
340     dstRect.y = 112;
341     dstRect.w = baseWidthVec_[1];
342     dstRect.h = baseHeightVec_[1];
343     if (!FillBaseLayer(layerVec[1], 1, zorder, dstRect)) {
344         return false;
345     }
346 
347     // navigation bar
348     zorder = 1;
349     dstRect.x = 0;  // Absolute coordinates, with offset
350     dstRect.y = 1488;
351     dstRect.w = baseWidthVec_[2];
352     dstRect.h = baseHeightVec_[2];
353     if (!FillBaseLayer(layerVec[2], 2, zorder, dstRect)) {
354         return false;
355     }
356 
357     return true;
358 }
359 
FillBaseLayer(std::shared_ptr<HdiLayerInfo> & showLayer,uint32_t index,uint32_t zorder,GraphicIRect & dstRect)360 bool HelloDrawing::FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,
361                                  uint32_t zorder, GraphicIRect &dstRect)
362 {
363     sptr<Surface> pSurface = basePSurfaceVec_[index];
364     sptr<Surface> cSurface = baseCSurfaceVec_[index];
365 
366     if (ProduceBuffer(pSurface, dstRect.w, dstRect.h, index, true) != SURFACE_ERROR_OK) {
367         LOGE("Produce cBuffer failed");
368         return false;
369     }
370 
371     OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
372     int32_t fence;
373     int64_t timestamp;
374     OHOS::Rect damage;
375     SurfaceError ret = cSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
376     if (ret != SURFACE_ERROR_OK) {
377         LOGE("Acquire cBuffer failed");
378         return false;
379     }
380 
381     GraphicIRect srcRect;
382     srcRect.x = 0;
383     srcRect.y = 0;
384     srcRect.w = dstRect.w;
385     srcRect.h = dstRect.h;
386 
387     GraphicLayerAlpha alpha = { .enPixelAlpha = true };
388 
389     showLayer->SetSurface(cSurface);
390     showLayer->SetBuffer(cbuffer, fence);
391     showLayer->SetZorder(zorder);
392     showLayer->SetAlpha(alpha);
393     // if rotate is not null, SetTransform
394     showLayer->SetCompositionType(GraphicCompositionType::GRAPHIC_COMPOSITION_DEVICE);
395     std::vector<GraphicIRect> visibleRegions;
396     visibleRegions.emplace_back(srcRect);
397     showLayer->SetVisibleRegions(visibleRegions);
398     std::vector<GraphicIRect> dirtyRegions;
399     dirtyRegions.emplace_back(srcRect);
400     showLayer->SetDirtyRegions(dirtyRegions);
401     showLayer->SetLayerSize(dstRect);
402     showLayer->SetBlendType(GraphicBlendType::GRAPHIC_BLEND_SRC);
403     showLayer->SetCropRect(srcRect);
404     showLayer->SetPreMulti(false);
405 
406     return true;
407 }
408 
Sync(int64_t,void * data)409 void HelloDrawing::Sync(int64_t, void *data)
410 {
411     struct OHOS::FrameCallback cb = {
412         .frequency_ = freq_,
413         .timestamp_ = 0,
414         .userdata_ = data,
415         .callback_ = std::bind(&HelloDrawing::Sync, this, SYNC_FUNC_ARG),
416     };
417 
418     OHOS::VsyncError ret = OHOS::VsyncHelper::Current()->RequestFrameCallback(cb);
419     if (ret) {
420         LOGE("RequestFrameCallback inner %{public}d\n", ret);
421     }
422 
423     if (!ready) {
424         return;
425     }
426 
427     Draw();
428 }
429 
Init(uint32_t width,uint32_t height,HdiBackend * backend)430 void HelloDrawing::Init(uint32_t width, uint32_t height, HdiBackend* backend)
431 {
432     this->backend = backend;
433 
434     baseWidthVec_.resize(BASE_LAYER_NUM);
435     baseHeightVec_.resize(BASE_LAYER_NUM);
436     baseCSurfaceVec_.resize(BASE_LAYER_NUM);
437     basePSurfaceVec_.resize(BASE_LAYER_NUM);
438 
439     if (BASE_LAYER_NUM == 3) {
440         baseWidthVec_[0] = 2560;
441         baseWidthVec_[1] = 2560;
442         baseWidthVec_[2] = 2560;
443         baseHeightVec_[0] = 112;
444         baseHeightVec_[1] = 1376;
445         baseHeightVec_[2] = 112;
446     }
447 
448     for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
449         CreateBaseSurface(i);
450     }
451     Sync(0, nullptr);
452 }
453 
CreateBaseSurface(uint32_t index)454 void HelloDrawing::CreateBaseSurface(uint32_t index)
455 {
456     sptr<IConsumerSurface> cSurface = IConsumerSurface::Create();
457     cSurface->SetDefaultWidthAndHeight(baseWidthVec_[index], baseHeightVec_[index]);
458     cSurface->SetDefaultUsage(BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA);
459 
460     sptr<IBufferProducer> producer = cSurface->GetProducer();
461     sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
462     cSurface->RegisterConsumerListener(this);
463 
464     baseCSurfaceVec_[index] = cSurface;
465     basePSurfaceVec_[index] = pSurface;
466 }
467 
CreatePyhsicalScreen()468 void HelloDrawing::CreatePyhsicalScreen()
469 {
470     screen = HdiScreen::CreateHdiScreen(output->GetScreenId());
471     screen->Init();
472     screen->GetScreenSupportedModes(displayModeInfos_);
473     size_t supportModeNum = displayModeInfos_.size();
474     if (supportModeNum > 0) {
475         screen->GetScreenMode(currentModeIndex_);
476         LOGI("currentModeIndex:%{public}d", currentModeIndex_);
477         for (size_t i = 0; i < supportModeNum; i++) {
478             LOGI("modes(%{public}d) %{public}dx%{public}d freq:%{public}d",
479                  displayModeInfos_[i].id, displayModeInfos_[i].width,
480                  displayModeInfos_[i].height, displayModeInfos_[i].freshRate);
481             if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
482                 this->freq_ = displayModeInfos_[i].freshRate;
483                 this->display_w = displayModeInfos_[i].width;
484                 this->display_h = displayModeInfos_[i].height;
485                 break;
486             }
487         }
488         screen->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
489         screen->SetScreenMode(currentModeIndex_);
490         LOGI("SetScreenMode: currentModeIndex(%{public}d)", currentModeIndex_);
491 
492         GraphicDispPowerStatus powerState;
493         screen->SetScreenPowerStatus(GraphicDispPowerStatus::GRAPHIC_POWER_STATUS_ON);
494         screen->GetScreenPowerStatus(powerState);
495         LOGI("get poweState:%{public}d", powerState);
496     }
497 
498     GraphicDisplayCapability info;
499     screen->GetScreenCapability(info);
500     LOGI("GetScreenCapability: name(%{public}s), type(%{public}d), phyWidth(%{public}d), phyHeight(%{public}d)",
501          info.name, info.type, info.phyWidth, info.phyHeight);
502     LOGI("GetScreenCapability: supportLayers(%{public}d), virtualDispCount(%{public}d)",
503          info.supportLayers, info.virtualDispCount);
504     LOGI("GetScreenCapability: supportWriteBack(%{public}d), propertyCount(%{public}d)",
505          info.supportWriteBack, info.propertyCount);
506     ready = true;
507 }
508 
OnScreenPlug(std::shared_ptr<HdiOutput> & output,bool connected,void * data)509 static void OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
510 {
511     LOGI("enter OnScreenPlug, connected is %{public}d", connected);
512     auto* thisPtr = static_cast<HelloDrawing *>(data);
513     thisPtr->OnHotPlugEvent(output, connected);
514 }
515 
OnHotPlugEvent(std::shared_ptr<HdiOutput> & output,bool connected)516 void HelloDrawing::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
517 {
518     /*
519      * Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
520      * initiated only after the initialization of the device is complete.
521      */
522     this->output = output;
523     deviceConnected_ = connected;
524 
525     if (!initDeviceFinished_) {
526         LOGI("Init the device has not finished yet");
527         return;
528     }
529 
530     LOGI("Callback HotPlugEvent, connected is %{public}u", connected);
531 
532     if (connected) {
533         CreatePyhsicalScreen();
534     }
535 }
536 
DoPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param)537 void HelloDrawing::DoPrepareCompleted(sptr<Surface>& surface, const struct PrepareCompleteParam &param)
538 {
539     BufferRequestConfig requestConfig = {
540         .width = display_w,  // need display width
541         .height = display_h, // need display height
542         .strideAlignment = 0x8,
543         .format = GRAPHIC_PIXEL_FMT_BGRA_8888,
544         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_FB,
545         .timeout = 0,
546     };
547 
548     if (surface == nullptr) {
549         LOGE("surface is null");
550         return;
551     }
552 
553     int32_t releaseFence = -1;
554     sptr<SurfaceBuffer> fbBuffer = nullptr;
555     SurfaceError ret = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
556     if (ret != 0) {
557         LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
558         return;
559     }
560 
561     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
562     tempFence->Wait(100); // 100ms
563 
564     uint32_t clientCount = 0;
565     bool hasClient = false;
566     const std::vector<LayerInfoPtr> &layers = param.layers;
567     for (const LayerInfoPtr &layer : layers) {
568         if (layer->GetCompositionType() == GraphicCompositionType::GRAPHIC_COMPOSITION_CLIENT) {
569             hasClient = true;
570             clientCount++;
571         }
572     }
573 
574     LOGI("fb fence is %{public}d, clientCount is %{public}d", releaseFence, clientCount);
575 
576     auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
577     if (hasClient) {
578         DoDrawData(addr, fbBuffer->GetWidth(), fbBuffer->GetHeight());
579     } else {
580         int32_t ret = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
581         if (ret != 0) {
582             LOGE("memset_s failed");
583         }
584     }
585 
586     BufferFlushConfig flushConfig = {
587         .damage = {
588             .w = display_w,
589             .h = display_h,
590         }
591     };
592 
593     /*
594      * if use GPU produce data, flush with gpu fence
595      */
596     ret = surface->FlushBuffer(fbBuffer, -1, flushConfig);
597     if (ret != 0) {
598         LOGE("FlushBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
599     }
600 }
601 
OnPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param,void * data)602 static void OnPrepareCompleted(
603     sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data)
604 {
605     if (!param.needFlushFramebuffer) {
606         return;
607     }
608 
609     if (surface == nullptr) {
610         return;
611     }
612 
613     if (data == nullptr) {
614         return;
615     }
616 
617     LOGI("OnPrepareCompleted param.layer size is %{public}d", param.layers.size());
618     auto* thisPtr = static_cast<HelloDrawing *>(data);
619     thisPtr->DoPrepareCompleted(surface, param);
620 }
621 
main(int32_t argc,const char * argv[])622 int32_t main(int32_t argc, const char *argv[])
623 {
624     HelloDrawing m;
625 
626     LOGI("start to HdiBackend::GetInstance");
627     HdiBackend* backend = OHOS::Rosen::HdiBackend::GetInstance();
628     if (backend == nullptr) {
629         LOGE("HdiBackend::GetInstance fail");
630         return -1;
631     }
632 
633     backend->RegScreenHotplug(OnScreenPlug, &m);
634     while (1) {
635         if (m.output != nullptr) {
636             break;
637         }
638     }
639 
640     if (!m.initDeviceFinished_) {
641         if (m.deviceConnected_) {
642             m.CreatePyhsicalScreen();
643         }
644         m.initDeviceFinished_ = true;
645     }
646     LOGI("Init screen succeed");
647 
648     backend->RegPrepareComplete(OnPrepareCompleted, &m);
649 
650     m.width_ = 480; // display width
651     m.height_ = 960; // display height
652     sleep(1); // wait 1s
653 
654     auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
655     auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
656     handler->PostTask(std::bind(&HelloDrawing::Init, &m, m.width_, m.height_, backend));
657     runner->Run();
658     return 0;
659 }
660