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