• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <vsync_helper.h>
28 #include <display_type.h>
29 #include <surface.h>
30 #include "hdi_backend.h"
31 #include "hdi_layer.h"
32 #include "hdi_layer_info.h"
33 #include "hdi_output.h"
34 #include "hdi_screen.h"
35 
36 #include "draw/color.h"
37 #include "draw/brush.h"
38 #include "draw/canvas.h"
39 #include "draw/pen.h"
40 #include "draw/path.h"
41 #include "draw/clip.h"
42 #include "effect/path_effect.h"
43 #include "effect/shader_effect.h"
44 #include "image/bitmap.h"
45 #include "image/image.h"
46 #include "utils/rect.h"
47 
48 #include "utils/matrix.h"
49 #include "utils/camera3d.h"
50 
51 using namespace OHOS;
52 using namespace Rosen;
53 using namespace Drawing;
54 
55 namespace {
56 /*
57  * base layer: status bar/launcher/navigation bar
58  */
59 constexpr uint32_t BASE_LAYER_NUM = 3;
60 }
61 
62 class HelloDrawing : public IBufferConsumerListenerClazz {
63 public:
64     void Init(uint32_t width, uint32_t height, HdiBackend* backend);
65     void DoDrawData(void *image, uint32_t width, uint32_t height);
66     void DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index);
67     void Draw();
68     void DrawSurface();
69     void Sync(int64_t, void *data);
70     void CreatePyhsicalScreen();
71     void DoPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param);
72     virtual void OnBufferAvailable() override;
73     SurfaceError ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width, uint32_t height, uint32_t index, bool baseLayer);
74     bool FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,  uint32_t zorder, IRect &dstRect);
75     bool DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec);
76     void CreateBaseSurface(uint32_t index);
77     void OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected);
78 
79     void TestDrawPathPro(Canvas &canvas, uint32_t width, uint32_t height);
80     void TestDrawImage(Canvas &canvas, uint32_t width, uint32_t height);
81 
82     uint32_t freq_ = 30;
83     uint32_t width_ = 0;
84     uint32_t height_ = 0;
85 
86     uint32_t display_w = 480;
87     uint32_t display_h = 960;
88 
89     bool initDeviceFinished_ = false;
90     bool deviceConnected_ = false;
91     std::shared_ptr<HdiOutput> output = nullptr;
92 
93 private:
94     uint32_t currentModeIndex_ = 0;
95     std::vector<DisplayModeInfo> displayModeInfos_;
96     std::vector<std::shared_ptr<HdiOutput>> outputs_;
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_OPAQUYE};
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 
190     Bitmap bitmap;
191     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUYE};
192     bitmap.Build(width, height, format);
193 
194     Canvas canvas;
195     canvas.Bind(bitmap);
196     canvas.Clear(Color::COLOR_WHITE);
197 
198     // TestDrawPathPro(canvas, width, height);
199     TestDrawImage(canvas, width, height);
200     constexpr uint32_t stride = 4;
201     int32_t addrSize = width * height * stride;
202     auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
203     if (ret != EOK) {
204         LOGE("memcpy_s failed");
205     }
206 }
207 
DoDrawBaseData(void * image,uint32_t width,uint32_t height,uint32_t index)208 void HelloDrawing::DoDrawBaseData(void *image, uint32_t width, uint32_t height, uint32_t index)
209 {
210     Bitmap bitmap;
211     BitmapFormat format {COLORTYPE_RGBA_8888, ALPHATYPE_OPAQUYE};
212     bitmap.Build(width, height, format);
213 
214     Canvas canvas;
215     canvas.Bind(bitmap);
216     canvas.Clear(Color::COLOR_RED);
217     if (index == 1) {
218         canvas.Clear(Color::COLOR_WHITE);
219         // TestDrawPathPro(canvas, width, height);
220         TestDrawImage(canvas, width, height);
221     }
222     constexpr uint32_t stride = 4;
223     int32_t addrSize = width * height * stride;
224     auto ret = memcpy_s(image, addrSize, bitmap.GetPixels(), addrSize);
225     if (ret != EOK) {
226         LOGE("memcpy_s failed");
227     }
228 }
229 
ProduceBuffer(sptr<Surface> & produceSurface,uint32_t width,uint32_t height,uint32_t index,bool baseLayer)230 SurfaceError HelloDrawing::ProduceBuffer(sptr<Surface> &produceSurface, uint32_t width, uint32_t height, uint32_t index, bool baseLayer)
231 {
232     OHOS::sptr<SurfaceBuffer> buffer;
233     int32_t releaseFence = -1;
234     BufferRequestConfig config = {
235         .width = width,
236         .height = height,
237         .strideAlignment = 0x8,
238         .format = PIXEL_FMT_RGBA_8888,
239         .usage = produceSurface->GetDefaultUsage(),
240     };
241 
242     SurfaceError ret = produceSurface->RequestBuffer(buffer, releaseFence, config);
243     if (ret != 0) {
244         LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
245         return ret;
246     }
247 
248     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
249     tempFence->Wait(100); // 100ms
250 
251     if (buffer == nullptr) {
252         LOGE("%s: buffer is nullptr", __func__);
253         return SURFACE_ERROR_NULLPTR;
254     }
255 
256     LOGI("ProduceBuffer: width: %{public}d height:%{public}d stride:%{public}d size:%{public}d",
257         buffer->GetWidth(), buffer->GetHeight(), buffer->GetBufferHandle()->stride, buffer->GetSize());
258 
259     auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
260     if (baseLayer) {
261         DoDrawBaseData(addr, buffer->GetWidth(), buffer->GetHeight(), index);
262     } else {
263         DoDrawData(addr, buffer->GetWidth(), buffer->GetHeight());
264     }
265 
266     BufferFlushConfig flushConfig = {
267         .damage = {
268             .w = width,
269             .h = height,
270         },
271     };
272 
273     int32_t acquireFence = -1;
274     ret = produceSurface->FlushBuffer(buffer, acquireFence, flushConfig);
275 
276     LOGI("Sync %{public}s", SurfaceErrorStr(ret).c_str());
277     return SURFACE_ERROR_OK;
278 }
279 
Draw()280 void HelloDrawing::Draw()
281 {
282     static int32_t count = 0;
283 
284     do {
285         std::vector<LayerInfoPtr> layerVec;
286         layerVec.resize(BASE_LAYER_NUM);
287         for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
288             std::shared_ptr<HdiLayerInfo> showLayer = HdiLayerInfo::CreateHdiLayerInfo();
289             layerVec[i] = showLayer;
290         }
291 
292         if (BASE_LAYER_NUM == 3) {
293             if (!DrawBaseLayer(layerVec)) {
294                 continue;
295             }
296         }
297 
298         output->SetLayerInfo(layerVec);
299 
300         IRect damageRect;
301         damageRect.x = 0; // Absolute coordinates, with offset
302         damageRect.y = 0;
303         damageRect.w = display_w;
304         damageRect.h = display_h;
305         output->SetOutputDamage(1, damageRect);
306 
307         backend->Repaint(outputs_);
308         count++;
309 #ifdef DEBUG_DUMP
310         std::string result;
311         output->Dump(result);
312         LOGI("Dump layer result after ReleaseBuffer : %{public}s", result.c_str());
313 #endif
314     } while (false);
315 }
316 
DrawBaseLayer(std::vector<LayerInfoPtr> & layerVec)317 bool HelloDrawing::DrawBaseLayer(std::vector<LayerInfoPtr> &layerVec)
318 {
319     // status bar
320     int32_t zorder = 1;
321     IRect dstRect;
322     dstRect.x = 0;  // Absolute coordinates, with offset
323     dstRect.y = 0;
324     dstRect.w = baseWidthVec_[0];
325     dstRect.h = baseHeightVec_[0];
326     if (!FillBaseLayer(layerVec[0], 0, zorder, dstRect)) {
327         return false;
328     }
329 
330     // launcher
331     zorder = 0;
332     dstRect.x = 0;  // Absolute coordinates, with offset
333     dstRect.y = 112;
334     dstRect.w = baseWidthVec_[1];
335     dstRect.h = baseHeightVec_[1];
336     if (!FillBaseLayer(layerVec[1], 1, zorder, dstRect)) {
337         return false;
338     }
339 
340     // navigation bar
341     zorder = 1;
342     dstRect.x = 0;  // Absolute coordinates, with offset
343     dstRect.y = 1488;
344     dstRect.w = baseWidthVec_[2];
345     dstRect.h = baseHeightVec_[2];
346     if (!FillBaseLayer(layerVec[2], 2, zorder, dstRect)) {
347         return false;
348     }
349 
350     return true;
351 }
352 
FillBaseLayer(std::shared_ptr<HdiLayerInfo> & showLayer,uint32_t index,uint32_t zorder,IRect & dstRect)353 bool HelloDrawing::FillBaseLayer(std::shared_ptr<HdiLayerInfo> &showLayer, uint32_t index,  uint32_t zorder, IRect &dstRect)
354 {
355     sptr<Surface> pSurface = basePSurfaceVec_[index];
356     sptr<Surface> cSurface = baseCSurfaceVec_[index];
357 
358     if (ProduceBuffer(pSurface, dstRect.w, dstRect.h, index, true) != SURFACE_ERROR_OK) {
359         LOGE("Produce cBuffer failed");
360         return false;
361     }
362 
363     OHOS::sptr<SurfaceBuffer> cbuffer = nullptr;
364     int32_t fence;
365     int64_t timestamp;
366     OHOS::Rect damage;
367     SurfaceError ret = cSurface->AcquireBuffer(cbuffer, fence, timestamp, damage);
368     if (ret != SURFACE_ERROR_OK) {
369         LOGE("Acquire cBuffer failed");
370         return false;
371     }
372 
373     IRect srcRect;
374     srcRect.x = 0;
375     srcRect.y = 0;
376     srcRect.w = dstRect.w;
377     srcRect.h = dstRect.h;
378 
379     LayerAlpha alpha = { .enPixelAlpha = true };
380 
381     showLayer->SetSurface(cSurface);
382     showLayer->SetBuffer(cbuffer, fence);
383     showLayer->SetZorder(zorder);
384     showLayer->SetAlpha(alpha);
385     // if rotate is not null, SetTransform
386     showLayer->SetCompositionType(CompositionType::COMPOSITION_DEVICE);
387     showLayer->SetVisibleRegion(1, srcRect);
388     showLayer->SetDirtyRegion(srcRect);
389     showLayer->SetLayerSize(dstRect);
390     showLayer->SetBlendType(BlendType::BLEND_SRC);
391     showLayer->SetCropRect(srcRect);
392     showLayer->SetPreMulti(false);
393 
394     return true;
395 }
396 
Sync(int64_t,void * data)397 void HelloDrawing::Sync(int64_t, void *data)
398 {
399     struct OHOS::FrameCallback cb = {
400         .frequency_ = freq_,
401         .timestamp_ = 0,
402         .userdata_ = data,
403         .callback_ = std::bind(&HelloDrawing::Sync, this, SYNC_FUNC_ARG),
404     };
405 
406     OHOS::VsyncError ret = OHOS::VsyncHelper::Current()->RequestFrameCallback(cb);
407     if (ret) {
408         LOGE("RequestFrameCallback inner %{public}d\n", ret);
409     }
410 
411     if (!ready) {
412         return;
413     }
414 
415     Draw();
416 }
417 
Init(uint32_t width,uint32_t height,HdiBackend * backend)418 void HelloDrawing::Init(uint32_t width, uint32_t height, HdiBackend* backend)
419 {
420     this->backend = backend;
421 
422     baseWidthVec_.resize(BASE_LAYER_NUM);
423     baseHeightVec_.resize(BASE_LAYER_NUM);
424     baseCSurfaceVec_.resize(BASE_LAYER_NUM);
425     basePSurfaceVec_.resize(BASE_LAYER_NUM);
426 
427     if (BASE_LAYER_NUM == 3) {
428         baseWidthVec_[0] = 2560;
429         baseWidthVec_[1] = 2560;
430         baseWidthVec_[2] = 2560;
431         baseHeightVec_[0] = 112;
432         baseHeightVec_[1] = 1376;
433         baseHeightVec_[2] = 112;
434     }
435 
436     for (uint32_t i = 0; i < BASE_LAYER_NUM; i++) {
437         CreateBaseSurface(i);
438     }
439     Sync(0, nullptr);
440 }
441 
CreateBaseSurface(uint32_t index)442 void HelloDrawing::CreateBaseSurface(uint32_t index)
443 {
444     sptr<Surface> cSurface = Surface::CreateSurfaceAsConsumer();
445     cSurface->SetDefaultWidthAndHeight(baseWidthVec_[index], baseHeightVec_[index]);
446     cSurface->SetDefaultUsage(HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA);
447 
448     sptr<IBufferProducer> producer = cSurface->GetProducer();
449     sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(producer);
450     cSurface->RegisterConsumerListener(this);
451 
452     baseCSurfaceVec_[index] = cSurface;
453     basePSurfaceVec_[index] = pSurface;
454 }
455 
CreatePyhsicalScreen()456 void HelloDrawing::CreatePyhsicalScreen()
457 {
458     screen = HdiScreen::CreateHdiScreen(output->GetScreenId());
459     screen->Init();
460     screen->GetScreenSupportedModes(displayModeInfos_);
461     outputs_.push_back(output);
462     size_t supportModeNum = displayModeInfos_.size();
463     if (supportModeNum > 0) {
464         screen->GetScreenMode(currentModeIndex_);
465         LOGI("currentModeIndex:%{public}d", currentModeIndex_);
466         for (size_t i = 0; i < supportModeNum; i++) {
467             LOGI("modes(%{public}d) %{public}dx%{public}d freq:%{public}d", displayModeInfos_[i].id, displayModeInfos_[i].width,
468                 displayModeInfos_[i].height, displayModeInfos_[i].freshRate);
469             if (displayModeInfos_[i].id == static_cast<int32_t>(currentModeIndex_)) {
470                 this->freq_ = displayModeInfos_[i].freshRate;
471                 this->display_w = displayModeInfos_[i].width;
472                 this->display_h = displayModeInfos_[i].height;
473                 break;
474             }
475         }
476         screen->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
477         screen->SetScreenMode(currentModeIndex_);
478         LOGI("SetScreenMode: currentModeIndex(%{public}d)", currentModeIndex_);
479 
480         DispPowerStatus powerState;
481         screen->SetScreenPowerStatus(DispPowerStatus::POWER_STATUS_ON);
482         screen->GetScreenPowerStatus(powerState);
483         LOGI("get poweState:%{public}d", powerState);
484     }
485 
486     DisplayCapability info;
487     screen->GetScreenCapability(info);
488     LOGI("GetScreenCapability: name(%{public}s), type(%{public}d), phyWidth(%{public}d), phyHeight(%{public}d)",
489         info.name, info.type, info.phyWidth, info.phyHeight);
490     LOGI("GetScreenCapability: supportLayers(%{public}d), virtualDispCount(%{public}d), supportWriteBack(%{public}d), propertyCount(%{public}d)",
491         info.supportLayers, info.virtualDispCount, info.supportWriteBack, info.propertyCount);
492 
493     ready = true;
494 }
495 
OnScreenPlug(std::shared_ptr<HdiOutput> & output,bool connected,void * data)496 static void OnScreenPlug(std::shared_ptr<HdiOutput> &output, bool connected, void* data)
497 {
498     LOGI("enter OnScreenPlug, connected is %{public}d", connected);
499     auto* thisPtr = static_cast<HelloDrawing *>(data);
500     thisPtr->OnHotPlugEvent(output, connected);
501 }
502 
OnHotPlugEvent(std::shared_ptr<HdiOutput> & output,bool connected)503 void HelloDrawing::OnHotPlugEvent(std::shared_ptr<HdiOutput> &output, bool connected)
504 {
505     /*
506      * Currently, IPC communication cannot be nested. Therefore, Vblank registration can be
507      * initiated only after the initialization of the device is complete.
508      */
509     this->output = output;
510     deviceConnected_ = connected;
511 
512     if (!initDeviceFinished_) {
513         LOGI("Init the device has not finished yet");
514         return;
515     }
516 
517     LOGI("Callback HotPlugEvent, connected is %{public}u", connected);
518 
519     if (connected) {
520         CreatePyhsicalScreen();
521     }
522  }
523 
DoPrepareCompleted(sptr<Surface> & surface,const struct PrepareCompleteParam & param)524 void HelloDrawing::DoPrepareCompleted(sptr<Surface> &surface, const struct PrepareCompleteParam &param)
525 {
526     BufferRequestConfig requestConfig = {
527         .width = display_w,  // need display width
528         .height = display_h, // need display height
529         .strideAlignment = 0x8,
530         .format = PIXEL_FMT_BGRA_8888,
531         .usage = HBM_USE_CPU_READ | HBM_USE_CPU_WRITE | HBM_USE_MEM_DMA | HBM_USE_MEM_FB,
532         .timeout = 0,
533     };
534 
535     if (surface == nullptr) {
536         LOGE("surface is null");
537         return;
538     }
539 
540     int32_t releaseFence = -1;
541     sptr<SurfaceBuffer> fbBuffer = nullptr;
542     SurfaceError ret = surface->RequestBuffer(fbBuffer, releaseFence, requestConfig);
543     if (ret != 0) {
544         LOGE("RequestBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
545         return;
546     }
547 
548     sptr<SyncFence> tempFence = new SyncFence(releaseFence);
549     tempFence->Wait(100); // 100ms
550 
551     uint32_t clientCount = 0;
552     bool hasClient = false;
553     const std::vector<LayerInfoPtr> &layers = param.layers;
554     for (const LayerInfoPtr &layer : layers) {
555         if (layer->GetCompositionType() == CompositionType::COMPOSITION_CLIENT) {
556             hasClient = true;
557             clientCount++;
558         }
559     }
560 
561     LOGI("fb fence is %{public}d, clientCount is %{public}d", releaseFence, clientCount);
562 
563     auto addr = static_cast<uint8_t *>(fbBuffer->GetVirAddr());
564     if (hasClient) {
565         DoDrawData(addr, fbBuffer->GetWidth(), fbBuffer->GetHeight());
566     } else {
567         int32_t ret = memset_s(addr, fbBuffer->GetSize(), 0, fbBuffer->GetSize());
568         if (ret != 0) {
569             LOGE("memset_s failed");
570         }
571     }
572 
573     BufferFlushConfig flushConfig = {
574         .damage = {
575             .w = display_w,
576             .h = display_h,
577         }
578     };
579 
580     /*
581      * if use GPU produce data, flush with gpu fence
582      */
583     ret = surface->FlushBuffer(fbBuffer, -1, flushConfig);
584     if (ret != 0) {
585         LOGE("FlushBuffer failed: %{public}s", SurfaceErrorStr(ret).c_str());
586     }
587 }
588 
OnPrepareCompleted(OHOS::sptr<Surface> & surface,const struct PrepareCompleteParam & param,void * data)589 static void OnPrepareCompleted(OHOS::sptr<Surface> &surface, const struct PrepareCompleteParam &param, void* data)
590 {
591     if (!param.needFlushFramebuffer) {
592         return;
593     }
594 
595     if (data == nullptr) {
596         return;
597     }
598 
599     LOGI("OnPrepareCompleted param.layer size is %{public}d", param.layers.size());
600     auto* thisPtr = static_cast<HelloDrawing *>(data);
601     thisPtr->DoPrepareCompleted(surface, param);
602 }
603 
main(int32_t argc,const char * argv[])604 int32_t main(int32_t argc, const char *argv[])
605 {
606     HelloDrawing m;
607 
608     LOGI("start to HdiBackend::GetInstance");
609     HdiBackend* backend = OHOS::Rosen::HdiBackend::GetInstance();
610     if (backend == nullptr) {
611         LOGE("HdiBackend::GetInstance fail");
612         return -1;
613     }
614 
615     backend->RegScreenHotplug(OnScreenPlug, &m);
616     while (1) {
617         if (m.output != nullptr) {
618             break;
619         }
620     }
621 
622     if (!m.initDeviceFinished_) {
623         if (m.deviceConnected_) {
624             m.CreatePyhsicalScreen();
625         }
626         m.initDeviceFinished_ = true;
627     }
628     LOGI("Init screen succeed");
629 
630     backend->RegPrepareComplete(OnPrepareCompleted, &m);
631 
632     m.width_ = 480; // display width
633     m.height_ = 960; // display height
634     sleep(1); // wait 1s
635 
636     auto runner = OHOS::AppExecFwk::EventRunner::Create(false);
637     auto handler = std::make_shared<OHOS::AppExecFwk::EventHandler>(runner);
638     handler->PostTask(std::bind(&HelloDrawing::Init, &m, m.width_, m.height_, backend));
639     runner->Run();
640     return 0;
641 }
642