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 ¶m);
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 ¶m)
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 ¶m, 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