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